Hi,
Lprogster wrote:I would really like to change this so I could play a variety of notes, possibly at different volumes. Is this possible? If so, a code example would be brilliant.
Generating single notes at different frequencies is easy. Anything more than that (e.g. 2 notes at same time, volume control, etc) is not.
In theory, it'd be possible to use an insane amount of CPU time and
"pulse width modulation" to gain a large amount of control over the PC speaker (including multiple different notes at the same time, volume control, and perhaps even playing several different digitized sounds at the same time with different volumes).
In practice, the PC speaker has very non-standard acoustic qualities. The same speaker in a small computer case has a different sound to the same speaker in a large computer case, different computers have different speakers, and some computers even use piezos instead of the 3.5 inch paper cone speaker that's fairly common. I'd assume the speaker driver electronics can also vary in quality (and effect the resulting sound), and might even include a low bandpass filter that makes pulse width modulation almost impossible. Lastly, it's usually impractical - an IRQ or SMI could create distortion and you'd need to disable task switches until all sound is completed.
Despite all of this, the idea is to generate a high frequency square wave where the duty cycle of the square wave is used to to control the "average" voltage applied to the speaker (and therefore the position of the speaker).
For example, for a sine wave you could send a stream like this to the speaker (where '1' is speaker output high and '0' is speaker output low):
1111 1110 1100 1000 0000 1000 11000 11110 1111
You could also take into account hysterisis. For example, if you want a square wave at 50% amplitude you could try sending a stream like this:
000000000000101010101010101010000000000
The problem is that the speaker takes time to move, and you'd end up with output that looks more like "________xxXXXXXXXXxx________". To reduce the effect of this you could try sending a stream like this:
000000000000111111101010101010000000000
Where the extra "ones" help to push the speaker to "half way" faster, and give you something closer to "________xXXXXXXXXXxx________". It's still not perfect, but it is slightly less imperfect...
To improve this you can use bias, so that silence is:
01010101010101010101010101010101
And the square wave at 50% amplitude looks like this:
0101010111111110110110110110110000000101010
This allows you to take into account hysterisis in both directions (where the "1111111" helps push the speaker to "75%" faster, and the "000000" helps to drop the speaker back to "25%" faster...
Cheers,
Brendan