DirectSound buffer with generated data

Started by
4 comments, last by AshleysBrain 15 years, 7 months ago
Hello, My friend recently asked me to write a program that generates square waves of configurable frequency. I used DirectSound before for playing static buffers without streaming, but adjustable frequency play, as I understand, would require having a streaming buffer. The streaming data would be generated on the fly ahead/behind of the play position, and I already looked at several tutorials on the subject, one of them from GameDev articles. I am trying to take some baby steps into this problem, so I created a single 2MB secondary buffer with 11050 sampling rate, 1 channel, and 8 bits per sample. I then filled the whole buffer with 0xFF (which would be the maximum sample amplitude allowed) and proceeded to play the buffer. What I heard was a very short blip, and then nothing. For some reason, I also heard the same blip when I stopped the buffer. To my understanding, I should have heard a long continuous beeping sound, because a 2MB buffer would have 2097152 samples, which at the rate of 11050 samples per second and 1 byte per sample would produce 189 seconds of sound. If my calculations are incorrect, I am sure this much data would produce at least more than a second. Does anyone know what's going on? I searched around but could not find anything like this.
Advertisement
Quote:Original post by ValMan
Hello,

My friend recently asked me to write a program that generates square waves of configurable frequency. I used DirectSound before for playing static buffers without streaming, but adjustable frequency play, as I understand, would require having a streaming buffer. The streaming data would be generated on the fly ahead/behind of the play position, and I already looked at several tutorials on the subject, one of them from GameDev articles.

I am trying to take some baby steps into this problem, so I created a single 2MB secondary buffer with 11050 sampling rate, 1 channel, and 8 bits per sample. I then filled the whole buffer with 0xFF (which would be the maximum sample amplitude allowed) and proceeded to play the buffer. What I heard was a very short blip, and then nothing. For some reason, I also heard the same blip when I stopped the buffer.

To my understanding, I should have heard a long continuous beeping sound, because a 2MB buffer would have 2097152 samples, which at the rate of 11050 samples per second and 1 byte per sample would produce 189 seconds of sound. If my calculations are incorrect, I am sure this much data would produce at least more than a second.

Does anyone know what's going on? I searched around but could not find anything like this.
The value in the sound buffer is effectively the position of the speaker. Setting the whole buffer to 0xff will cause the speaker to go at maximum and sit there, not moving - so no sound.
Square sound waves are normally repeating, they don't just sit at 0xff for the full duration, they go from 0xff to 0x00.

If you want to get a steady tone, use a sine wave instead.
Thank you very much Steve! I was starting to suspect the same thing, but sadly my knowledge about sound is very minimal. Now I will just need to figure out how many samples to fill in based on frequency, I think I can do that myself. I believe the formula is Samples per Cycle = Sample Rate / Frequency (taken from Programming Windows by Charles Petzold). Half a cycle would be filled with 0xFF in my case, and the other half will be filled with 0x80 because 0x80 is silence for 8-bit sample size.
Quote:Original post by ValMan
I believe the formula is Samples per Cycle = Sample Rate / Frequency (taken from Programming Windows by Charles Petzold).

That's right, the period of a wave in seconds (the time it takes for one full cycle) is 1 divided by the frequency. Multiplying this by the sample rate gives you the period in samples.

Quote:Half a cycle would be filled with 0xFF in my case, and the other half will be filled with 0x80 because 0x80 is silence for 8-bit sample size.

Filling the buffer with any same value causes silence - as Steve said, this won't move the speaker cone at all (the waveform can be thought of as the speaker cone position over time when using traditional loudspeakers). You could use 0x00 instead of 0x80 - and you'll get a louder tone, since the amplitude of the wave is greater.
Construct (Free open-source game creator)
Thank you for your help, but I didn't get the second part of your answer. I do understand about speaker cone position, and I understand now that the whole buffer can't be filled with the same value. However, I said in my earlier post that for each square wave I would fill the samples with 0xFF for loudness and 0x80 for silence, and I guess you are saying I was wrong?

To my understanding, square waves are like sine waves except their data varies instantly (like a switch between true/false) instead of in a smooth line like sin(). It would therefore follow that the period, or "cycle" would consist of two parts, where the first part is completely loud (0xFF) and the second part is completely silent (0x80), not necessarily in that order but without any transitions between them. The size of the whole period/cycle in bytes would be Sample Size * Samples Per Cycle. In my case sample size is 1 byte, so that's easy. The size of half a cycle would be Sample Size * Samples Per Cycle / 2. So I will fill the first (SamplesPerCycle / 2) bytes with 0xFF and the next (SamplesPerCycle / 2) bytes with 0x80, and will go on repeating this loop until the whole buffer is filled. Or in the case of streaming, until the available space in the buffer is filled. This will then result in a continuous square wave of a certain frequency being played through the speaker without interruption.

Perhaps what you were trying to say is that my bytes must vary with each SAMPLE, as in 0x80 0xFF 0x80 0xFF (and so on) instead of with each CYCLE. I will have to do more testing when I get home.
You've got the right idea. Don't worry about the silence thing - it's only relevant if the entire buffer is filled with the same data, which is why you'd hear nothing when every sample is 0xFF.

There's no correct pair of values to use. It's just the volume. 0x80 and 0x81 would be a very quiet wave. 0x80 and 0xFF, as you are using, would be a fairly high volume. 0x00 to 0xFF would be even louder, because the values are even further apart. The choice is arbitrary. The way you're doing it sounds fine :)
Construct (Free open-source game creator)

This topic is closed to new replies.

Advertisement