Chapter 7 · 7 practice questions · In-browser grading · Local storage

Implement the Equations in JavaScript and Review

Turn the equations into small JavaScript functions, then review how range, frequency, sonar mode, and element count affect the result.

Overall0 / 360%
This page0 / 7Correct answers
StoragelocalStorage onlyNo data sent to a server

What this chapter does

In this chapter, we implement the equations from earlier chapters as small JavaScript functions. As you read, connect each mathematical symbol to the corresponding function name, argument, and return value.

The first half explains the code. The exercises in the second half review how range, frequency, passive versus active operation, and element count work together.

Map each equation to a function first

ValueEquation or ideaJavaScript function
Sound speed cThe Mackenzie approximation using temperature, salinity, and depthmackenzieSoundSpeedMps
Absorption coefficient αThe course's frequency-only teaching formulaabsorptionDbPerKm
Wavelength λλ = c / fwavelengthM
One-way transmission loss TLk log10(R) + αR / 1000transmissionLossDb
Round-trip time2R / croundTripTimeSec
Directivity index DIThe idealized 10 log10(N)arrayGainDb
Passive SNRSL - TL - (NL - DI)passiveSnrDb
Active SNRSL - 2TL + TS - (NL - DI)activeSnrDb

For example, wavelengthM divides sound speed by frequency and returns wavelength. Pairing each function with one equation makes the longer code listing much easier to follow.

Validate inputs before calculating

The implementation uses standard JavaScript and no external libraries. Before calculating, it checks that a value is finite, that it falls within the chosen range, and that element count is a positive integer.

An invalid value is not silently rounded or clamped. Instead, the code throws a RangeError, making it clear which input violated the equation's assumptions. The code runs as written in current major browsers and Node.js.

The minimal JavaScript implementation

function assertFiniteNumber(name, value) {
  if (!Number.isFinite(value)) {
    throw new RangeError(`${name} must be a finite number`);
  }
}

function assertRange(name, value, min, max) {
  assertFiniteNumber(name, value);
  if (value < min || value > max) {
    throw new RangeError(`${name} must be in [${min}, ${max}]`);
  }
}

function assertPositiveInteger(name, value) {
  if (!Number.isInteger(value) || value <= 0) {
    throw new RangeError(`${name} must be a positive integer`);
  }
}

function mackenzieSoundSpeedMps(tempC, salinityPsu, depthM) {
  assertRange('tempC', tempC, 2, 30);
  assertRange('salinityPsu', salinityPsu, 25, 40);
  assertRange('depthM', depthM, 0, 8000);
  return 1448.96
    + 4.591 * tempC
    - 5.304e-2 * tempC ** 2
    + 2.374e-4 * tempC ** 3
    + 1.340 * (salinityPsu - 35)
    + 1.630e-2 * depthM
    + 1.675e-7 * depthM ** 2
    - 1.025e-2 * tempC * (salinityPsu - 35)
    - 7.139e-13 * tempC * depthM ** 3;
}

// Educational simplified absorption formula (frequency only).
// Derived in form from François-Garrison (1982) / Ainslie-McColm (1998),
// but with temperature, salinity, pH and depth dependence removed.
// For field design, use the full models with environmental inputs.
function absorptionDbPerKm(frequencyKhz) {
  assertRange('frequencyKhz', frequencyKhz, 0.4, 200);
  const f2 = frequencyKhz ** 2;
  return 0.11 * f2 / (1 + f2)
    + 44 * f2 / (4100 + f2)
    + 0.000275 * f2
    + 0.003;
}

function wavelengthM(soundSpeedMps, frequencyHz) {
  assertRange('soundSpeedMps', soundSpeedMps, 1300, 1700);
  assertRange('frequencyHz', frequencyHz, 1, 1_000_000);
  return soundSpeedMps / frequencyHz;
}

function transmissionLossDb(rangeM, frequencyKhz, spreadingCoeff = 20) {
  assertRange('rangeM', rangeM, 1, 1_000_000);
  assertRange('spreadingCoeff', spreadingCoeff, 10, 20);
  return spreadingCoeff * Math.log10(rangeM)
    + absorptionDbPerKm(frequencyKhz) * (rangeM / 1000);
}

// roundTripTimeSec: returns 2R / c.
// Lower bound on rangeM is 1 m because a zero range is physically meaningless
// for a sonar problem (target would coincide with the transducer).
function roundTripTimeSec(rangeM, soundSpeedMps) {
  assertRange('rangeM', rangeM, 1, 1_000_000);
  assertRange('soundSpeedMps', soundSpeedMps, 1300, 1700);
  return (2 * rangeM) / soundSpeedMps;
}

function arrayGainDb(elementCount) {
  assertPositiveInteger('elementCount', elementCount);
  return 10 * Math.log10(elementCount);
}

function passiveSnrDb(sourceLevelDb, tlDb, noiseLevelDb, diDb) {
  return sourceLevelDb - tlDb - (noiseLevelDb - diDb);
}

function activeSnrDb(sourceLevelDb, tlDb, targetStrengthDb, noiseLevelDb, diDb) {
  return sourceLevelDb - 2 * tlDb + targetStrengthDb - (noiseLevelDb - diDb);
}

This is the minimum code needed to trace the relationships used in the course. A real deployment would also account for surface and seafloor loss, reverberation, refraction, bandwidth, and detection thresholds.

Read the code in four groups

  1. Validate the inputs: assertFiniteNumber, assertRange, and assertPositiveInteger stop invalid values before calculation.
  2. Find the basic environmental quantities: mackenzieSoundSpeedMps returns sound speed, and absorptionDbPerKm returns absorption per kilometer.
  3. Calculate range- and array-related quantities: wavelengthM, transmissionLossDb, roundTripTimeSec, and arrayGainDb each implement the equation shown in the table above.
  4. Calculate SNR last: passive sonar subtracts one-way TL once; active sonar subtracts the round-trip 2TL.

Read one function at a time from its inputs to its return value. In particular, follow the value returned by transmissionLossDb into the two SNR functions to see how the full calculation connects.

Connect everything in the review

The exercises that follow mix direct function calculations with questions about how sonar is used. If useful, run the code in your browser's developer tools or in Node.js and check the result.

You have completed the review when you can explain, from both the equations and the functions, why increasing range raises TL, why increasing frequency shortens wavelength but raises absorption, and why adding elements increases DI.

Review the implementation and sonar fundamentals

0 / 7 correct. Results are saved only in this browser's localStorage.

Chapter 7 / Practice 1
Unanswered

Q30. Calculate the value returned by roundTripTimeSec

roundTripTimeSec(rangeM, soundSpeedMps) is called with (1500, 1500). How many seconds does it return?

Show hint
Round-trip time is 2 × range / c.
Show reasoning
2 × 1500 / 1500 = 2, so the function returns 2.0 s.
Chapter 7 / Practice 2
Unanswered

Q31. Calculate the value returned by wavelengthM

wavelengthM(1500, 30000) is called. How many meters does it return?

Show hint
Wavelength is 1500 / 30000.
Show reasoning
1500 / 30000 = 0.05, so the function returns 0.05 m.
Chapter 7 / Practice 3
Unanswered

Q32. Identify the exception used for invalid input

If the implementation receives a negative range or an out-of-range temperature, which type of exception does it throw?

Show hint
Use the exception that reports a value outside its allowed range.
Show reasoning
The code throws RangeError to make it clear that an input is outside the range allowed by the equation.
Chapter 7 / Practice 4
Unanswered

Q33. Calculate the array gain for 10 elements

arrayGainDb(10) is called. Approximately how many dB does it return?

Show hint
10 log10(10).
Show reasoning
10 log10(10) = 10, so about 10 dB.
Chapter 7 / Practice 5
Unanswered

Q34. Find the active-SNR improvement when range is halved

Ignore absorption and consider spherical spreading only. Halving the range reduces one-way TL by about 6 dB. Approximately how much does active-sonar echo SNR improve?

Show hint
The active-sonar equation contains the round-trip term 2TL.
Show reasoning
Reducing one-way TL by 6 dB affects the round trip twice, so active SNR improves by about 12 dB. This question ignores absorption. Because transmissionLossDb includes absorption, its actual return value also depends on frequency.
Chapter 7 / Practice 6
Unanswered

Q35. Decide which sonar mode pays the larger range penalty

In the same environment, as range increases, which mode becomes less favorable more quickly under the basic sonar equations?

Show hint
In active sonar, sound travels to the target and back.
Show reasoning
The active-sonar equation contains 2TL, so increasing range causes a larger loss than it does in passive sonar.
Chapter 7 / Practice 7
Unanswered

Q36. Choose a method for monitoring without transmitting

You want to monitor whale calls and shipping noise without transmitting sound. Which approach should you choose first?

Show hint
Choose a method that listens to surrounding sound without transmitting.
Show reasoning
A passive hydrophone array receives underwater sound without transmitting, so it fits this use case.

Where this course leaves you

  • Mapping mathematical inputs and outputs directly to JavaScript arguments and return values makes the implementation easier to follow.
  • When an input violates an equation's assumptions, the code stops clearly with RangeError.
  • Sound speed, transmission loss, array gain, and passive and active SNR can be built as separate functions and then combined.
  • Real-world design also adds refraction, reverberation, surface and seafloor scattering, and detection thresholds.