Computer systems often need to interface with devices that have analog outputs. Pulse width modulation (PWM) is a familiar method for simulating analog signals using digital outputs. With this technique, the amount of power a system receives depends on the duty cycle of the PWM signal. By varying the duty cycle, or the ratio of time the signal is high to low, a digital system is able to continuously vary the output of a given system while maintaining a constant frequency (Arduino PWM pins produce signals at 490Hz or at 980Hz). The number of applications PWM works with is vast and includes servo motor positioning, DC motor speed control, LED brightness, and sound effects. PWM can be applied to make sounds with a speaker, but the frequency needs to be modified to generate various tones.
Every sound humans encounter consists of one or more frequencies, and the way the ear interprets those sounds is called pitch. The pitch of a sound may be its true frequency, or may be a result of overtones which are perceived as a particular pitch. In music, specific frequencies of sound have been named, and doubling of these fundamental frequencies results in the same notes in higher octaves. For example, 55Hz is called A1, and 110Hz is A2. The next octave, A3, is double of A2, or 220Hz. To find the frequency of a note in any other octave, take the frequency of the current octave and multiply it by 2^n, where n is the number of octaves up or down. So, to find the frequency of A6 from A4 (440Hz) calculate 440Hz•(2²)=440Hz•4=1760Hz; A3 would be 440Hz•(2^-1)=440Hz•½=220Hz.
In order to produce a variety of pitches, a digital signal needs to convey the frequency of sound it is trying to reproduce. The simplest approach is to generate a 50% duty cycle pulse stream and set the frequency to the desired pitch. In order to generate a specific frequency, the period of the note needs to be found, which is the amount of time it takes for the signal to cycle once. This is done by taking the inverse of the frequency (Period=1/Frequency). Once that value is known, it's a simple matter of keeping the signal high for half the length of the period, and low for the other half. So in order to produce an A4 note, one would find the period of that note, 1/440 = 2.2727 milliseconds. From there, hold the signal high for 1.13636 milliseconds, and low for the same amount of time.
The process above is the basic algorithm that the built-in Arduino tone() function performs. However, instead of simply toggling the selected pin high and low, the algorithm uses internal timer pre-scalers to achieve a higher precision frequency, and thus closer pitch. By using timers instead of solely software-based toggling, the system is able to eliminate delays caused by processes not directly related to toggling of the pins, such as iterating counters in for-loops. Additionally, the use of hardware timers allows for tones to be generated continuously, regardless of other events occurring. This is exactly the same behavior seen in the Arduino's PWM functionality. In fact, according to documentation, the use of tone() interferes with PWM output on pins 3 and 11, which indicates that the timer normally used to generate the 490Hz Arduino PWM frequency is modified to create other frequencies.
To demonstrate the difference between the built-in tone() function in Arduino and "manually" generating the same tone via for-loops, the A4 note (440Hz) was synthesized via the functions individually, and then simultaneously on both pins. In both cases the "manually" made tone is about 5Hz slower than the tone() function's tone. This is true even when the tones are played separately, which shows that tone() is neither interfering with the for-loop-based method, nor is it affected by other processes the Arduino performs. The delay in the for-loop method is a result of the Arduino needing to perform other processes between calls to the tone generation function.
A PWM signal with a 50% duty cycle is considered a square wave, because the time spent high is equal to the time spent low. Changing the duty cycle while keeping the frequency the same doesn't change the pitch of the sound, but it does affect the way the ear and brain interpret it. This results from the fact that square waves consist of the sum of a near-infinite number of sinewaves, specifically the odd harmonics. Harmonics are higher-frequency components of some fundamental frequency. For example, if a signal is oscillating at fundamental frequency of 100Hz, the second harmonic would be oscillating at twice the rate, or 200Hz, the third would be at 400Hz, and so on. This is the basis for notes: as discussed above, the A1 note is 55Hz, the A2 is 110Hz, A3 is 220Hz. Each is a multiple of the fundamental 55Hz frequency. Odd harmonics are the odd-multiplier of the fundamental frequency, or every other note in the sequence (A3, A5, A7, for example). Thus, when a square wave is heard, the brain interprets it at the frequency the signal is being generated at, but the other less dominant frequencies also play a role in affecting the character of the sound. If the duty cycle is changed, the sound and its harmonic composition changes. Yamaha Synth has an excellent article on the topic of square waves and harmonics, and is recommended for anyone interested in exploring the topic further. According to the article, altering the duty cycle from 50% results in the sound going from "hollow and woody" to "nasal or tight".
The component frequencies can be viewed with the help of the OpenScope and WaveForms Live using the Fast Fourier Transform (FFT) function. In simple terms, an FFT is a mathematical process used to find the component frequencies of any signal. This is extremely similar to a spectral analysis performed on light, which shows which wavelengths are present. In this case the frequencies in an electrical signal, instead of light wave, are being interpreted. Amplitude in terms of voltage is plotted on the y-axis, and the frequencies are plotted on the x-axis. The image below, from the Wikipedia article on FFTs, visualizes what an FFT does.
To demonstrate the concept of harmonics, an FFT of the note A4 was performed, shown below.
By doing an FFT of A4, it becomes clear that only the odd harmonics are present in the signal: 1, 320Hz = 3 x 440Hz; 2, 200Hz = 5 x 440Hz; 3, 080Hz = 7 x 440Hz.
To explore the effect of using a duty cycle other than 50%, the Arduino was used to generate the default 490Hz PWM signal with duty cycles from 10% to 90% in 10% steps. The animation below shows the changes in the component frequencies as the duty cycle is altered.
This demonstrates that as the duty cycle of a pulsed signal is changed, the component frequencies also shift around. If some of these component frequencies are undesirable, it is possible to filter them out and thus modify the quality of the sound. However, there is a limit to what a pulsed signal driving a speaker can achieve. Generating natural-sounding tones requires more sophisticated techniques and hardware.
PCM is the method used in most digital audio formats such as CDs, computer files, and telephones. In order to represent an analog signal, such as a sine wave, the recording device samples the audio at a set sampling rate. Each time a sample is taken, the level of the signal is recorded as a binary number. The length of the binary numbers, and thus number of discrete levels a signal can be represented at, depends on the resolution of the recording device. During playback, the decoder converts the binary number stream into an analog signal using a digital-to-analog converter, thereby reproducing the sine wave that was originally recorded. This process requires filtration, as high-frequency noise is generated by the transitions between the different output levels when the analog signal is being reconstructed.
PDM is not as widespread due to lack of adoption by the music industry. The idea behind PDM is that a sinewave can be described by pulse density, which is determined by varying both the duty cycle and frequency of the signal. As a sinewave moves from the trough to the peak, the pulse density goes from 0% to 100% by increasing the duty cycle and frequency of the signal. For example, if the pulses are viewed as 1s and 0s, a sinewave could be described by the following stream of bits (going from trough to peak to trough):
The advantage of this method is that it only requires a low-pass filter with a suitable cutoff frequency to convert the digital signal to analog. This technique is technically possible on the Arduino with minimal external components (a capacitor and resistor), while PCM would require a dedicated digital-to-analog converter integrated circuit.