Acoustic roughness
When two pure tones are nearly in tune, you hear beats. The perceived pitch is the average of the two pitches, and you hear it fluctuate as many times per second as the difference in frequencies. For example, an A 438 and an A 442 together sound like an A 440 that beats four times per second. (Listen)
As the difference in pitches increases, the combined tone sounds rough and unpleasant. Here are sound files combining two pitches that differ by 16 Hz and 30 Hz.
16 Hz: http://www.johndcook.com/beats_16Hz_diff.wav
30 Hz: http://www.johndcook.com/beats_30Hz_diff.wav
The sound becomes more pleasant as the tones differ more in pitch. Here's an example of pitches differing by 100 Hz. Now instead of hearing one rough tone, we hear two distinct tones in harmony. The two notes are at frequencies 440-50 Hz and 440+50 Hz, approximately the G and B above middle C.
100 Hz: http://www.johndcook.com/beats_100Hz_diff.wav
If we separate the tones even further, we hear one tone again. Here we separate the tones by 300 Hz. Now instead of hearing harmony, we hear only the lower tone, 440+150 Hz. The upper tone, 440+150 Hz, changes the quality of the lower tone but is barely perceived directly.
300 Hz: http://www.johndcook.com/beats_300Hz_diff.wav
We can make the previous example sound a little better by making the separation a little smaller, 293 Hz. Why? Because now the two tones are an octave apart rather than a little more than an octave. Now we hear the D above middle C.
293 Hz: http://www.johndcook.com/beats_293Hz_diff.wav
Update: Here's a continuous version of the above examples. The separation of the two pitches at time t is 10t Hz.
Continuous: http://www.johndcook.com/continuous.wav
Here's Python code that produced the .wav files. (I'm using Python 3.5.1. There was a comment on an earlier post from someone having trouble using similar code from Python 2.7.)
from scipy.io.wavfile import writefrom numpy import arange, pi, sin, int16, iinfoN = 48000 # sampling rate per secondx = arange(3*N) # 3 seconds of audiodef beats(t, f1, f2): return sin(2*pi*f1*t) + sin(2*pi*f2*t)def to_integer(signal): # Take samples in [-1, 1] and scale to 16-bit integers m = iinfo(int16).max M = max(abs(signal)) return int16(signal*m/M)def write_beat_file(center_freq, delta): f1 = center_freq - 0.5*delta f2 = center_freq + 0.5*delta file_name = "beats_{}Hz_diff.wav".format(delta) write(file_name, N, to_integer(beats(x/N, f1, f2)))write_beat_file(440, 4)write_beat_file(440, 16)write_beat_file(440, 30)write_beat_file(440, 100)write_beat_file(440, 293)
In my next post on roughness I get a little more quantitative, giving a power law for roughness of an amplitude modulated signal.