Sounds Library Unit

Here's a new PMP library unit for making sounds on your PIC. There are commands for simple beeps (good for annunciators or tactile feedback when pressing pushbuttons), as well as for playing musical passages or making percussive sounds.


This library unit and its commands is designed to make sounds on your PIC. There are three basic ways to get that going:
  • connect a piezo directly to an output pin if volume is not an issue,
  • or use a small loudspeaker with a series resistor and blocking capacitor,
  • or connect to an audio amplifier/speaker combo for room-filling sound.
In any event, the commands in this unit will let you generate a number of different sounds.

Compilation Constants

Only one port pin is required, that to which you connect one of the audio output devices described above. You specify the port pin to be driven by means of two compiler constants. For example, for B.0, the following will be needed:


Global Constants

For convenience when using the tone() command, I've included constants to assign frequencies to the 88 notes of a standard piano. The notes are A, B, C, D, E, F and G, of course, and with an S, a sharp is indicated. The digit suffix specifies in which octave the note lies. So, for example, the lowest note on the piano is NOTE_A0, which is followed by A# in that octave (NOTE_AS0). And the highest note is NOTE_C8. Just to be sure you're clear on the concept, you can either specify 440 Hz as a frequency explicitly, or by NOTE_A4; both will produce the same pitch.

The values are the frequencies rounded to the nearest whole number. Since the equally tempered scale is generated by multiplication by an irrational number (12th root of 2), this implies that the musicality may suffer slightly, especially on the low end of the scale. However, the tuning is quite reasonable elsewhere.


The first set of commands is for making beeps, useful as simple annunciators. The three tones can be low, mid or high pitched. The beep time is specified in milliseconds.

lowBeep(duration : word);
midBeep(duration : word);
highBeep(duration : word);

Note that these three simple commands can be used at any PIC oscillator speed, and further, do not use any hardware resources.

The next command is used to generate a broader range of more musical pitches.

tone(freq, duration : word);

where the frequency is specified in Hertz and the duration in milliseconds. The frequency may span 20 Hz to 20 kHz, i.e., the range for normal human hearing.

To make sure there is enough time for low frequencies to produce at least one cycle, the duration should be at least 50 milliseconds, though this can be reduced as the frequency increases, e.g., the minimum time required for one cycle of 440 Hz is about 2 milliseconds.

To avoid internal computational overflow, the maximum duration should be no more than 65,535 milliseconds (about 1 minute).

Observe that the PMP delay_ms(duration) command is also measured in milliseconds, hence can be used to creates rests or tacits with the same unit of measurement as the tone() command.

The tone() command depends upon Timer1 running at 1 MHz. The necessary prescaler for this is automatically calculated and loaded. Observe that Timer1 is only running when the tone() command is called. Therefore you can use it elsewhere in your program when tone() is not currently called. Moreover, no   interrupts are used.

In the current version, only master PIC oscillator frequencies of 4, 8, 16 and 32 MHz are supported for the tone() command. Obviously, the absolute musical pitch depends upon the accuracy of the PIC oscillator, among other things. While no symphony orchestra would want to use it and while this is not up to laboratory standards, the command is perfectly fine for conveying simple tunes, especially in the middle of its range.

Finally, the following command can be utilized to make bursts of  noise, similar to what you hear on a radio tuned between stations:

noise(duration : word);

Again, duration is measured in milliseconds and can be as high as 65,535 milliseconds (about 6 minutes). Like tone() this command employs Timer1, but only when the command is actually called. Therefore, you can use the timer yourself for other things in between times. No interupts are used.

The algorithm used for the noise source is a linear shift register of length 31, with taps at the 28th and 31st bits.

Like the tone() command, only PIC oscillator speeds of 4, 8, 16 and 32 MHz are supported at this time.

The noise source is great for creating percussive and unpitched sounds like the chuff-chuff of a locomotive train, rain falling on the roof, etc. When modulated at a very rapid rate, it can also make all manner of weird "space" effects.

Add It to Your Library Collection

You can get the Sounds library unit "Sounds.pas" by clicking the following link:

Be sure to read over the source code for additional details on how to use it.

Try It Out

You'll no doubt want to try this out to see what it can do, so I've written four demo programs for you. The first keeps things simple with the three beep commands. The second shows off the complete piano range of notes. The third actually plays a song you might remember from childhood. And the fourth demonstrates the noise generator. Click here to get the entire package of all four demos.

You can use the same schematic from this exercise to connect up a piezo, speaker and/or amplifier.

No comments:

Post a Comment