Two tones with different frequencies presented at the same sound pressure level (SPL) may not sound equally loud. Equal-loudness contours represent these variations in perceived loudness across frequencies for the average human ear. The basis of the equal-loudness contour is the phon, the dB SPL necessary for a tone to sound as loud as a 1000-Hz reference tone. For example, if a given tone is perceived to be as loud as a 60-dB tone at 1000 Hz, it has a loudness of 60 phon. Equal-loudness contours are defined by the international standard ISO/IEC 226 (2003).
I recently came across this MatLab function for producing equal-loudness contours according to the current standard. I ported it to Python below. The functions return the frequencies and dB SPL values associated with a given phon value. In some circumstances, it may be useful to know the inverse of this (i.e., what is the phon value of a tone with a given frequency and level?), so this is provided as well:
It is worth pointing out that there are other factors that influence the loudness of a tone besides frequency and level, which are not accounted for by the ISO/IEC standard. For instance, longer sounds generally sound louder than shorter ones, and the standard contours are valid only for 'side-presented' sounds (i.e., via headphones).
Here is a reproduction of the classic contour plot created using the functions above (styled using the seaborn package):
- ISO/IEC (2003). ISO/IEC 226:2003 Acoustics -- Normal equal-loudness-level contours. http://www.iso.org/iso/catalogue_detail.htm?csnumber=34222.