Project: Ultrasound Dosimeter

ASA Abstract: It is well known that hearing loss can occur from exposure to high intensities of sounds >80 dBA; however there is less information about hearing loss from ultrasonic frequencies. There are many commercial and industrial devices that produce ultrasonic acoustic energy ranging from humidifiers, pest and pet repellent devices, and crowd control devices. Even though there are fewer regulations with regard to ultrasound, there have been documented cases of effects including temporary or permanent threshold shifts from exposure to ultrasonic energy. However, there is not a readily available open source solution for quantifying exposure.
In this work, a TYMPAN open source hearing aid development platform is used to develop and test a prototype ultrasonic dosimeter. This dosimeter works like a SPL meter, with the inclusion of the ultrasonic 1/3 octave bands, with an audible alarm emitted when the user happens to be in the presence of ultrasonic energy. From the full data recording of a test covering various environments, several key features of the exposure are highlighted.
The presentation will cover the development of the algorithms, testing of the device, and post test analysis. Code will be made available via the open source libraries for future users to build upon.

So far, I’ve been able to (I think) calculate a level for the frequencies below a low pass filter cutoff, for comparison to levels above a high pass filter cutoff. At the same time, the output from the highpass filter goes to a frequency shifter so that ultrasonic energy comes into the audio band.

I’m trying to play the frequency shifted ultrasound to the left audio channel and the lowpass filtered (not shifted) to the right audio channel, but I’m not getting anything out on the right. If I switch the output and put the ultrasound to the right it works, so the headphones and connection are working. Is it possible to put out different things to the left and right headphone, or am I chasing down something that fundamentally won’t work?

Here’s a snippet of the audio connections part of the code:
AudioConnection_F32 patchCord10(i2s_in, 0, hp_filt1, 0); //connect the Left input to high pass filter - this is the ultrasound channel
AudioConnection_F32 patchCord20(hp_filt1, 0, calcLevelUltra, 0); //connect the high pass filter to the level time weighting
AudioConnection_F32 patchCord30(i2s_in, 0, freqShift, 0); //use the Left input
AudioConnection_F32 patchCord40(freqShift, 0, gain1, 0); //connect to gain
AudioConnection_F32 patchCord50(gain1, 0, i2s_out, 0); //connect to the left output

AudioConnection_F32 patchCord11(i2s_in, 0, lp_filt1, 0); //connect the right input to low pass filter - this is the regular channel
AudioConnection_F32 patchCord21(lp_filt1, 0, calcLevelFull, 0); //connect the low pass filter to the level time weighting
AudioConnection_F32 patchCord41(calcLevelFull, 0, gain2, 0); //connect to gain
AudioConnection_F32 patchCord52(gain2, 0, i2s_out, 1); //connect in+gain to the right output

Hi jCooper!

Your code looks pretty good, except for patchCord41. Do you really want to come out of the calcLevelFull object? I’m not sure that calcLevelFull outputs any audio, so that might be why it is silent.

Instead, perhaps one of these two is what you meant?

  • AudioConnection_F32 patchCord41(lp_filt1, 0, gain2, 0); //connect to gain

  • AudioConnection_F32 patchCord41(i2s_in, 0, gain2, 0); //connect to gain

Good luck! Post back to let us know how it works out!


Thank you! that was it exactly. If I send lp_filt1 through to the gain, it works just as I’d hoped.

Next issue: When I use the built in mic and put the Tympan in front of a 40Khz ultrasound ranger (it actively pings, and is called PING))) from parallax), I pick up energy spread all over in frequency, including plenty in the audio band. When I stick my ears in front of the pinger, I hear nothing, which is what I was expecting. My theory is that the blue case on the Tympan is somehow doing nonlinear things and converting the 40 kHz clicks into more broadband energy. So, I was going to try again with an external mic instead. However, the only thing I have access to at home is the kind of headphones with mic built in, like you’d use with your phone or to join a zoom call. Not picking up anything but electronic noise on those - not sure if I have a setting wrong (I tried both
and I tried turning up the input gain) or these mics aren’t suitable for the job. Any insight?


My first thought is that the pinger might actually be so loud that it is saturating the Tympan’s input. That would spread energy everywhere. Ways to check:

  • have the Tympan record the input audio to its SD card and then open the WAV file on the PC/Mac. If the WAV file is saturating, the Tympan’s input was saturating.

  • Turn down the Tympan’s input gain (it’s probably set for 15 or 20 dB, if you’re using any of the example programs). Lowering the gain will help avoid saturation. Set it to zero dB of gain and see if the prob goes away.

  • Move farther away. That’ll make the ultrasound less intense (ie quieter) and might avoid saturation. Or turn the Tympan away from the source. Or put a sheet of paper in-between to attenuate. (Ultrasound can bounce really well off walls and tables, so you still might get strong signals.) Distance is probably the best thing to try.

Your idea to try a diff mic is a good one, though you never know what mics happen to work in the ultrasound. Yours not working is probably about its plug. Does it have two plugs: one for its mic and one for its earphones? Or does it have just one plug? If it has just one plug, it prob won’t work. Look closely at the plug and you’ll see that it’s got 4 metal contacts (separated by three black bands) instead of the usual 3 metal contacts. Our jacks are only built for the 3 not the 4. You can buy a splitter, but that prob doesn’t help right now.

My guess is that you’re saturating. My guess is that you’ll avoid saturation by turning the gain down to 0 dB anf giving yourself 6 ft of separation. Record to SD to confirm. That’s what I’d recommend.

Let me know what you find!

(Replied via phone…sorry for garbled finger-typing)

Chip, Thank you so much.
With the 15 dB input gain, it was saturating, as you suspected. Additionally, the “40kHz” ping is obviously of very short duration, which means it has a wide bandwidth, wide enough to reach Nyquist when the sample rate is 96kHz. So even at a lower input gain, I was hearing low frequency sound that was actually an aliased signal. Looking at a spectrogram made that clear.

Also, I noticed some aliasing also when recording a flute or other musical instruments, even though the signal was well below Nyquist. I suspect that a low pass filter needs to be added before the digitization, but that’s incompatible with the variable sample rate in the Tympan.


You brought up so many interesting topics!

  • Ping Duration: Most of the inexpensive transducers have a bandwidth of 2-3kHz, so I would expect that a 40 kHz ping from these devices is, at shortest, about 0.3-0.5 msec in duration. I would be very curious to see the waveform and spectrogram. Can you share any recordings are views of the ping? If all you have is a screenshot, you can post pictures here on the forum simply by dragging a JPG or whatever into the message that you compose here.

  • Non-Linear Transducers, not Aliasing?: As for the broader observation of aliasing, I would be interested to see an example of what you’re hearing. Given my personal experience with using this ADC, I’ve seen very little aliasing. When I see unexpected frequency content, it is usually due to my transducers that either generated the signal or due to my transducers that received the signal. These inexpensive ultrasound pingers are especially messy when they’re hit super-hard with strong electrical signals.

  • Air is Non-Linear to Ultrasound!: In addition to these inexpensive transducers being non-linear, remember that the air itself is non-linear to ultrasonic audio. Have you ever played with these devices: They exploit this property of ultrasound in air to generate ultra-focused audible sound beams. They’re amazing!

And then you also commented about anti-aliasing filtering…especially the issue of how does one have adequate anti-aliasing filtering in front of variable rate data acquisition system. I, too, have always had this question. Then, because of this program, I was forced to finally learn the answer!

  • Sigma-Delta ADCs: You might not be familiar with sigma-delta type ADCs. These are the class of ADCs that have been used in digital audio systems for 3 decades now. Sigma-delta converters are not like the type of ADCs that we were all taught about in school. They have some seriously-cool properties…

  • Samples at Megahertz Rate: In a sigma-delta converter, they actually sample the signal at a rate of several megahertz. It can achieve this speed because it only does this sampling at a 1-bit resolution. It then takes this megahertz-class 1-bit data stream and applies a digital low-pass filter (the “decimation filter”). Because of the averaging going on (that’s what a lowpass filter is), the output of the filter is a 16-24 bit audio stream at whatever final sample rate that you have requested.

  • The Digital Filters Do the Heavy Work: As long as the system provides analog anti-alias filtering for signals above the underlying megahertz-class sample rate, the digital filtering takes care of the rest. Even though sigma-delta ADCs have been around for decades, I still find them to be an amazing invention.

  • Our Decimation Filter: In the case of our audio converter (TI AIC3206), the plot below shows the response of the decimation digital filter in the Nyquist region (Nyquist is at 0.5). This graph scales to whatever sample rate you’ve selected. Note that any content above Nyquist ought to be attenuated by at least 73 dB. So, if you are hearing aliasing, it must be very quiet?

I’m not at all denying your ears. Ears are the gold standard. If you have recordings showing the aliasing that you’re hearing, can you share them? Or share a spectrgram? I’d love to learn from what you’re finding!

All great points, Chip. I still have a lot to learn about the sigma delta A-D. And it’s consistent with my spectrograms that show a bit of energy from >45 kHz wrapping around to 0-5 kHz when there’s no processing and no aliasing in the ch2 image (has a 10kHz frequency shift down).

Note that I’m pretty sure all the levels are off (160 dB spectral level is obviously not right) in these spectrograms. I must be missing a factor - is there an extra conversion factor of some kind in the .wav files recorded to the SD card?

I had the input gain at 15 dB for the musical instruments and recorded with the built in Tympan mic.

I have the .wav files if those help - not sure the best way to share them.

with the 25 dB gain on the ultrasound ranger, it’s obvious in this time series that there’s clipping.

Is there anything more glorious than a spectrogram? I don’t think so. I LOVE THEM!

Based on your spectrograms, I’ve got two comments:

  • Faster Sample Rates!: Perhaps you’d benefit from running at an even faster sample rate! Be aware that the Tympan can run faster than 96 kHz. I’ve barely used it at higher speeds, so I don’t really know how well it works, but it is possible to run faster. With RevE, I think that you can ask for any sample rate that you want up to 192 kHz. I don’t know how well it really runs at these super-fast speeds, but if you’re interested in getting a bit more frequency extension, ask for something faster and see what happens!

  • Dynamic Range of the Plots: I see in your spectrograms that your colorbar is 0 to 160 dB…thereby showing a dynamic range of 160 dB. That’s a lot of dynamic range. A large dynamic range is indeed very revealing…but maybe unrealistically so? Do you have other data acquisition systems that, even when plotted with this much dynamic range, are free of the aliasing? If so, that’s fantastic! For Tympan, that is indeed probably more than can be expected. I can’t tell by looking at your plot…but if you plotted only ~120 dB of dynamic range (so +40 to +160) does that make the aliasing disappear from the plots?

If you are able share the files, that would be fantastic, because I’m so curious! I could then look at this dynamic range issue myself. I sent you an email based on an address from our ASA communications.

As for the scaling of your WAV files to make plots, given that it is an uncalibrated system (until you calibrate it), the absolute level is meaningless. So, I wouldn’t worry about your values being so large. If you ever choose to calibrate your system using a known SPL acoustic stimuli, that’ll help you scale all your values.

It is a bit surprising that your time-domain waveform plot shows a span of -32768 to +32768. Those are very correct numbers, but if you’re using Matlab, the traditional way to read audio files is to use [wav,fs_Hz]=audioread('myfilename.wav');. When you use audioread() it brings the values in so that, instead of +/-32768, they values span +/-1.0. If you’re using Matlab, are you using a something like wav=fread(fid,'int16'); instead?

Either is equally correct, so continue to do whichever you’d prefer…I’m simply being nosey and trying to learn how other people like to work. :slight_smile:


Dynamic Range: you’re quite right that 160 dB dynamic range is ridiculous. I zoomed in and found that what I’m calling aliased energy from the pinger is only about 20-30 dB down from the very loud peak at 40kHz. Regardless, I HEAR the ping at low frequency in the audio on the channel without frequency shifting. I’m typically doing a 1kHz low pass filter on that side, but I tried it with and without and there was not a significant difference. If there was something interesting happening after the A-D, I would have expected the lowpass filter to knock it out.

Higher Sample Rate: definitely worth trying. I have some samples recorded at 176400 Hz, but not the pinger.

Wav files: I’m using Matlab’s audioread like
[y,Fs] = audioread(‘pingerAt0dBgain.WAV’,‘native’);
I’ve found in other work that the ‘native’ input can be key and if you don’t do that the reader might clip the values.

I didn’t know about that ‘native’ keyword on audioread. Very cool!

I looked at the audio file that you sent of the pinger. Lots of cool things to see…

Pulse width is 0.25-0.8 msec (depending upon your definition of “pulse width”) which means that most of the energy fits within a bandwidth of 1250 Hz or maybe to 4000 Hz (depending upon your definition of “energy of a pulse”). Of course, in an spectrogram, we’ll see sidelobes that’ll extend to a wider range of frequencies. They won’t hold as much energy as the core bandwidth, but we will certainly see energy across a wider range of frequencies due to the spectrogram’s wide dynamic range.

The pinger’s pulse repetition period is about 100 msec, so it blasts at a 10 Hz rate. This is unrelated to the issue of aliasing, but it is fun to see how fast it’s pining. Unrelated, I also see that there is a small DC offset to the signal, which is a common artifact of audio data acquisition systems (including ours).

Looking below at a spectrogram with 120 dB of dynamic range, we see that the pings appear to be centered a bit above 40 kHz. That’s not surprising, so I think that this looks pretty good!

Looking at the same spectrogram with 160 dB of dynamic range, we reveal more signal components down near the noise floor. This is information that is in the recording, so I agree that is absolutely important to be aware of it, but it is comforting that (for this slice at least) it’s down pretty deep.

The spectrogram above was of an early part of the recording. As we can see, there isn’t much content at other frequencies that is synchronized with the pulses. In other words, I don’t see much that could be considered aliasing. If we look at a later time, however, we see a different behavior; we see that the 40kHz pulses do have a signal component down in the low frequencies:

It turns out that the presence of the low-frequency component is related to the strength of the 40 kHz pulse. The weakest pulses do not produce the low-frequency components while the strongest pulses do. At least, that’s my conclusion from looking at the data. When I look at the strongest pulse in the recording, I find that the low-frequency component (ie < 15kHz) has an RMS that is 45 dB below the RMS of the core part of the pulse (>28 kHz). So, it’s small in terms of overall energy, but not small relative to the dynamic range of the Tympan or of your hearing. Stated simply: it is relevant.

Whether these low-frequency components are an artifact of the Tympan’s mic or ADC or whether they are actually in the air as legitimate sound, that is an open question in my mind. With the inexpensive transducers I’ve used, I do often hear an audible component of the transmissions when I’m standing next to the devices during my testing. So, at least some of it is “real”.

Thank you for allowing me to ramble on about your data. I love data!

Trying to get myself back on track (ie, helping you with your questions), I presume that it’s the low-frequency components that you’re referring to as the aliasing? If so, yay! …I now know specifically what you’re talking about. Thanks for sending me the audio recording so that I can understand.

Looking a bit more at this low-frequency artifact…

The figure below shows the full pulse and it shows just the low-frequency component of the pulse. Intriguingly, the low-frequency component is just a downward half-pulse.

Anecdotally checking the rest of the pulses, they all seem to be a downward half-pulse. No upward pulses and nothing more than the half pulse. I don’t know what that implies, but it is interesting to me.

With regard to your dosimeter, do these kinds of signal artifacts affect your thinking about your project? What concerns to you have? How can I help you move forward?

All interesting findings!

In the big picture of getting a dosimeter to work, I don’t think these artifacts are really a major issue. Something to document, but not something that keeps it from achieving the desired performance. I was able to get it to register “ultrasound detected” when I thought it should and not when I thought it shouldn’t, so that’s something.

The only real outstanding thing I wanted to add (Eventually, probably not before ASA because of various schedule constraints) is a slower time average. I’m doing the sound levels in octave (And above 20kHz in 1/3 octave) bands, which necessitated doing it in the frequency domain. So I’m seeing the levels for a single FFT. If, for example, that FFT window didn’t line up with one of the pings, it wouldn’t register unusual ultrasonic energy. But it would on one of the subsequent FFTs that did align with a ping. I’d like to move to more of an integration in time over several FFTs, more like how your time domain sound level meter example works. But that seemed to require passing more variables around than I really know how to do in C++ :grin:

Just for fun, I recorded the ultrasound pinger again, with the sample rate set at 176400Hz and input gain 0 dB. It isn’t clipping, but the energy is spread throughout the entire spectrum. Some of that could be fun artifacts of how I did the spectrogram or something, but I definitely hear it. Very interesting to have made it to the point where we can ponder hardware and acoustics instead of just trying to get something running!

I did some measurements of the how well the Tympan works at these high sample rates. If you’re interested, I started a new thread here: