Friday, January 19, 2018

Measuring Audio Latency

For real-time audio processing, it is often important to minimize the delay between audio coming out of the system compared to the audio coming into the system.  This is especially true of hearing aids, where too much latency can cause the listener to perceive an echo (or have a comb-filtering effect), which end up degrading rather than helping the listener's experience.  Research suggests that the maximum tolerable latency in a hearing aid is only 14-30 msec.  If Tympan wants to be helpful, we need to make sure that we keep our latency shorter than this.  Let's find out what our system does!

Test Setup.  To measure the latency of the Tympan, we need to inject an audio signal into the Tympan and then measure delay of the output audio relative to the input audio.  There's lots of ways that this can be done.  I chose to use the setup shown in the picture above.  In this setup, I generate my test audio signals from my PC.  I use a series of 1 kHz tone bursts that are 1 second long.  The audio comes out of my PC and (as shown in the red line) is split so that it goes to the input of the Tympan *and* to the input of an audio recorder.  The output of the Tympan is then (as shown in the blue line) routed to the other input of the audio recorder.  The stereo audio file produced by the audio recorder will contain the input audio in the left channel and the output audio in the right channel.  It will then be a simple post-processing analysis to measure the delay between the two channels.

Raw Data.  An example recording and an example Matlab processing script are in my GitHub here.  The plot above shows the example data.  As you can see, there are three tone bursts in the recording.  At this timescale, one cannot see any delay between the signals, but that is because we are not zoomed in enough.  The plot below zooms in to the start of one of the tone bursts.  Here, we definitely see that the Tympan output has a slight delay relative to the direct audio signal.

Analysis.  Using the plot above, we could visually assess the latency between the two channels.  But, to do even better, I included a Matlab script in the GitHub directory that computes the cross-correlation between the two channels.  The best estimate of the latency will be when when the cross-correlation is maximum.  For this recording, the best estimate of the latency is 3.1 msec.  That's nice and short!

Measuring other Tympan Configurations.  Expanding from this single measurement, I then repeated the process and measured the latency for a variety of different configurations of the Tympan.  I tried different audio block sizes and I tried different audio processing algorithms.  My results are shown in the figure below.  The simple 3.1 msec value reported above can be seen in the bottom-left of the plot as the first point on the yellow line.  All of the other configurations result in increased latency, but there are still a lot of configurations that are shorter than the 14-30 msec upper limit from the literature.

Components of the Latency.  After working with the system for a while, I've identified three contributors to the latency:

  • Hardware:  The audio interface for the Tympan is a TI 3206 AIC.  This chip has a pipeline that is 17 samples long on the input and 21 samples long for the output.  So, for this round-trip testing, it contributes 38 samples of latency, which at sample rate of 24 kHz is a latency of 1.58 msec.
  • Audio Library:  The Tympan audio library is based on the Teensy audio library, which has employs a queue of two audio blocks in order to prevent audio hiccups and drop-outs.  In the Tympan library, this audio block size is configurable, hence my ability to make the graph above where I vary the block size.  For a block size of 16 samples, the library's latency is 2*16=32 samples, which is 1.33 msec at 24 kHz.  Totaled with the hardware latency (1.58 msec + 1.33 msec), we get 2.9 msec, which is very close to the 3.1 msec value that I measured.  Great!
  • Audio Processing:  Beyond the audio library, most any actual audio processing will also introduce additional latency.  A typical (symmetric) FIR filter, for example, will result in a group delay that is half the length of the FIR filter.  Other filters and other operations (such as FFT) introduce delays as well.  The specific amount of latency may vary, but some latency is inherent in the math.  For the Tympan, we see the latency for FIR and FFT in the graph above.
Optimizing for Minimum Latency.  From this exploration, I've learned that latency can be minimized by (1) using the shortest audio block size that the system can handle and (2) running the simplest audio processing algorithm that you can get away with.  On this latter point, we all want our audio processing to have extremely fine frequency resolution.  But, high resolution requires long FIR filters or long FFTs.  Long FIRs/FFTs introduce a lot of latency, however.  So, if you want low latency, you need to use the shortest FIRs and FFTs that you can.

Tuesday, December 19, 2017

Adding a Real Time Clock to the Tympan

In talking with users of the Tympan, data logging is something that they'd like the Tympan to do.  Furthermore, for the data logging to be useful, the data needs to be time stamped.  So, the Tympan needs to know the time and date.  Normally, one needs to add a dedicated real-time clock (RTC) circuit for a device to know the time and date.  Luckily, the Teensy 3.6 that is at the heart of the Tympan has most of the required elements already built in.  Let's finish it off to make it work!
My Tympan with the RTC mod.  The red wire is the only indication that it has been modified.
What is a RTC?  A real-time clock is a circuit that keeps time despite the device itself being turned on or off.  The RTC works because it is usually provided its own power via a small coin cell battery.  The Teensy 3.6 includes all the components that we need except for this battery.  Normally, you could simply connect a coin cell and you would be done.

Use our LiPo Battery Instead of a Coin Cell.  For Tympan, I don't want to try to squeeze a coin cell battery into the Tympan's enclosure.  We already have a perfectly good battery in the system (the LiPo battery that powers the whole device).  Can't we use that battery for the RTC, too?  I think that we can.

Providing Power, Even When "Off".  There are two tricks to using the LiPo battery.  First, we need to bring the LiPo power to the RTC circuit on the Teensy even when the Tympan's power switch is set to "off".  In other words, we have to be choosy about where we grab the LiPo power when we bring it to the RTC.  Second, before we connect the LiPo to the RTC, we need to step down the LiPo voltage (3.7-4.2V) so that it won't damage the RTC (< 3.6V).
The red arrows show the many choices for where to grap the LiPo power for the Teensy's RTC.  I chose to grab the LiPo power from the Fuse F1, as shown by the heavy red arrow.
Choosing the Connection Point.  The figure above is an excerpt from the Tympan schematic (full schematic here).  It shows the elements of the circuit related to the LiPo battery (BT1) and the power swtich (SW1).  I added red arrows to show all the locations that we could grab the LiPo battery voltage prior to the power switch.  Any of these will work.  The specific place that we chose will be driven by which spot is easiest to reach with a soldering iron.

Stepping Down the Voltage.  After choosing place to grab the LiPo power, we need to step down its voltage to a safe level.  One can use a variety of techniques.  Since the current draw for the RTC is very, very low (about a microamp?), I chose to use a simple voltage divider.
Designing the Voltage Divider.  According to the datasheet for the Teensy' microprocessor, the voltage at the RTC battery pin needs to be between 1.71V and 3.6V.  We need to step down the LiPo voltage to say within these bounds.  To decide what resistor values to use, I am going to assume that the LiPo can go down to 3.3V and maybe as high as 5V (which would only happen if I were to make a wiring mistake while hacking).  Given these limits, I chose to use a 50K resistor (high side) and a 125K resistor (low side).  As can be seen in the graph below, these resistor values mean that the voltage will be good for any RTC current draw up to 10-50 microamps.  Looks great!

Wire it Up.  Given this voltage divider design, the picture below shows what I did.  I chose to grab the LiPo voltage by soldering the 50K resistor to side of the fuse F1.  I chose to grab ground by soldering the 125K resistor to TP2 (which is ground).  The RTC VBat is taken from the midpoint between the two resistors.  I soldered a short red wire from the mid point up to the hole on the Teensy for the RTC VBat.  Because these modifications are so small, the modified Tympan fit back into its enclosure without any issues (as shown in the photo at the top of this post).
Testing the RTC.  To test the real time clock, I used one of the Teensy example programs.  The RTC example programs are part of the "Time" library that comes with the Teensysduino installer.  If you didn't install the Time library, go back and re-install Teensyduino and you should be good.  The specific example program that I used was "TimeTeensy3".  I made no modifications to the program.  It compiled and uploaded to the Tympan without any issues.

To test the RTC on the Tympan, I used the "TimeTeensy3" example program that was made for the Teensy.
It works!  The example program is set to simply print the Teeny's time and date to the serial port.  it does this once a second.  By opening the Arduino Serial Monitor, you can see the time and date from the Tympan.  It is correct!  I then unplugged the Tympan, turned the Tympan power switch to the off position.  Normally, this loss of power would cause the Tympan to lose track of time.  On my newly-modified Tympan, the RTC should still be getting power from the LiPo battery via the voltage divider.  After a few minutes, I turned the Tympan back on and opened up the Serial Monitor.  The Tympan was still showing the correct time and date.  It works!

The "TimeTeensy3" example program commands the Teensy to print out the RTCs understanding of the time and date.  This output can be viewed through the Arduino Serial Monitor.  It works!  Even after cycling the Tympan's power, it still works!
How Does RTC Work on the Teensy?  As far as I can tell, the RTC on the Teensy is simply a counter.  It simply counts the oscillations of a quartz crystal (or whatever).  The Teensy knows how many counts occur every second, so it does not the time relative to when the RTC started counting.  But when did the RTC start counting?  What is the reference time?  For the Teensy Time library, the reference time is taken to be the time and date when the sketch was compiled.  The library gets the computer's system time and incorporates that into the program.  Since the RTC is reset just after compilation is complete, the compile time is a decent approximation for the reference time.  No special action from the user is needed.  This is a pretty nice setup.

Losing RTC Power,  The only problem with this setup is if the RTC counter loses power.  In my case, this would happen if the LiPo becomes fully drained.  When the RTC counter loses power, it loses its count.  When power is restored, the RTC will start counting again from zero.  The reference time, however, will not have been reset.  So, when we ask the RTC what time it is, it'll use the original reference time and we'll get the wrong answer.  So, if the LiPo becomes fully discharged, you'll want to reset the RTC by recompiling and re-uploading the program, or by looking at the Time library to figure out how to manually set the time.

Overall, I was impressed at how easy it was to get the RTC working on this system.  A couple of resistors and a piece of wire?  Easy!  Now that the Tympan knows the time and date, it'll be much more useful as data logging device.  For future users of Tympan, I'm looking forward to incorporating this modification.  But, for those of you with the current version of Tympan (Rev C), you'll have to get out the soldering iron.  Maybe you're like me and find that to be a fun thing to do!

Friday, May 26, 2017

Calibrating My Earphones with the Tympan

At its core, a hearing aid is a microphone, an amplifier, and an earphone.  Each element is critical to the quality of the sound produced by the device.  For the Tympan, it (currently) is simply the amplifier (ie, the electronics) -- you have to bring your own microphones and speakers.  In my last post, I looked at a few different microphones.  Today, I'm going to look at some earphones.  I'm going to calibrate a set of earphones with the Tympan to measure the frequency response and overall loudness.
Earphones:  The earphones that I'm going to calibrate are my Klipsch S4 earbuds.  They are absolutely nothing special.  They are simply low-cost, consumer-level earbuds like anyone might have.  I think that inexpensive earbuds are where a lot of people will start when using the Tympan, so it's where I'm going to start with my earphone calibration.

Setup:  My overall setup is shown in the figure above.  I'm using the the Tympan electronics to drive the earbuds.  The Tympan has been programmed to generate a tone that sweeps from low frequency to high frequency .  The earbuds are fixed in a coupler, which mates to a laboratory-grade microphone (B&K 4192) and data acquisition system.  So, by generating tones at known digital level in the Tympan, I can measure the corresponding sound pressure level produced by the earbuds in the 2cc coupler.
Using the B&K 4949 2cc Coupler
Coupler:  The coupler is a very important part of this setup.  Earbuds are supposed to be worn in an ear canal.  There is very little volume in your ear canal that the earbud needs to drive.  So, if you want to measure the response of an earbud, you need to use a coupler that creates a similar small-volume environment.

Which Coupler to Use?  There are two typical choices for couplers for this kind of testing: (1) an ANSI-standard 2cc coupler, or (2) a so-called "artificial ear".  While the artificial ear is designed to give a more realistic response, a basic 2cc coupler is what the ANSI standard uses for hearing aid assessment, so that's what I'm starting with.  My 2cc coupler is a B&K Type 4946, shown above.
Fitting my earbud to the coupler's adapter.  The output of the earbud should be flush with the hole in the adapter plate.

Fitting the Earbud:  The 4949 includes different adapter pieces to help fit a variety of hearing aid styles.  For my earbud, I chose to use the broad dish-shaped adapter piece intended for in-the-ear hearing aids.  As you can see above, I used putty to hold the earbud in place and positioned the earbud such that the output of the earbud is flush with the opening of the adapter.  It isn't pretty, but I think that it gets the job done.

Completing the Setup:  Once the earbud and adapter plate were fit to one end of the coupler, I inserted the measurement microphone into the other end of the coupler.  I connected the earbuds to the Tympan electronics and programmed the electronics to produce frequency sweeps at different digital levels (my code is on my GitHub here).
My setup used to calibrate the Tympan output with my Klipsch consumer-level earbuds.
Raw Data:  Some raw data from this measurement is shown below (raw data is in my GitHub here).  It is the measured sound output from the earpbud as measured by the microphone in the 2cc coupler.  This microphone is calibrated to units of Pascals from which sound pressure level (SPL) is easily computed.  As you can see, I had the Tympan generate five frequency sweeps, each one at a louder amplitude.

Raw data recorded from the Klipsch earbuds during this calibration testing.
Actual Amplitude:  In my Arduino code, I thought that I was commanding the amplitude to step from 0.1 up to 1.0.  In later analysis, however, I discovered that the ToneSweep object from the Teensy Audio library only produces half the amplitude that you think.  So, when you command "1.0", you actually get an amplitude of 0.5.  I confirmed through by sending the audio out the USB Audio connection to the PC.  It was half.  So, instead of spanning 0.1 to 1.0, my test spanned only 0.05 to 0.5.

Low-Level Noise:  When I looked at this raw data in the frequency domain (see spectrogram below), I was surprised to see this strange, low-level background noise appear at the higher drive levels.  It first appears at a digital drive level of 0.25.  What is this?  At lower drive levels it is not there -- it just magically appears at 0.25.  This is very strange.
Spectrogram of audio produced by the Tympan via the Klipsch earbuds during the calibration tests.  When the drive amplitude is 0.25 and above, a low-level background noise appears.
[Follow-Up: Additional testing suggests that this noise might be related to the Tympan's audio codec (TI 3206) struggling to deliver the required current to these low impedance (18 ohm) earbuds.  That's my current working theory, but I cannot yet definitely confirm that that's the issue.  I'll have to do more examination of this in the future.]

Data Analysis:  From this raw data, I divided the recording to isolate each frequency sweep.  Then I measured the SPL at each frequency (analysis code here, more Matlab functions here).  For each drive amplitude, the measured response is shown in the figure below.  As expected, the frequency response is basically independent of amplitude, which is good.
Measured frequency response for different drive levels.
The Bottom Line:  The figure below is how I chose to summarize these results.  The red line is the measured frequency response and loudness when driving at an amplitude of 0.25, which is when that low-level noise/distortion appears.  The blue line is the frequency response that I measured at my strongest drive level (0.5 relative to full scale) that I then scaled up as if I had driven it at the hardware's maximum drive level (1.0 relative to digital full scale).  As can be seen, at 1 kHz, the system should be able to produce about 117 dB SPL at full drive.
Bass Boost:  A secondary result that is obvious in this graph is that these earphones do not have a flat frequency response.  Not at all.  These consumer-level earphones clearly provide a strong boost to the frequencies below, say, 500 Hz.  I'm guessing that this bass boost this was a conscious decision by the designers in order to appeal to a certain segment of the earbud market.  This is perhaps not the ideal response for a hearing instrument.  I'm curious to test other earphones to see which earbuds might have a more flat response.

Caveat:  An important caveat to this work is that the measurements were taken using a 2cc coupler.  Your ear is NOT the same as the 2cc coupler.  In a real ear, the frequency response could be quite different.  Perhaps the overal SPL produced by the earphones will be higher (or lower).  These are important questions.  So, in the future, I'd like to repeat these tests using an artificial ear, which should better simulate a real ear.  Will the results be different than on the 2cc coupler?  I look forward to finding out!

Sunday, May 21, 2017

Calibrating Microphones with Tympan

One goal of our open source hearing aid platform ("Tympan") is to get people to experiment with new sound processing algorithms but another goal of the Tympan is to enable people to experiment with different microphones and speakers.  So, with regards to microphones, we designed the Tympan electronics to have several different kinds of inputs to allow it to support a range of microphones.  Today, I'll start by calibrating three different microphones with the Tympan.  Then, in a later post, I'll look at how the different microphones influence the self-noise of the system.

Microphones:  The three microphones that I'm using today are shown above.  There's the "Sony Mic", which  is a lapel electret mic intended for picking up voice.  Then, there is the "PCB Mic", which is an inexpensive surface-mount silicon MEMS mic that we've included on the Tympan PCB.  And, finally, there's the "Knowles Mic", which is a high-sensitivity, low-noise mic intended for use in hearing instruments like hearing aids.

Why Calibrate?  If you calibrate your microphones, your audio processing will be able to look at the in-coming digital data and know what sound level is happening in the real world.  Knowing the true sound level in the different frequency bands allows you to tailor your algorithms (amplification, compression, noise reduction) to better respond to a person's specific hearing loss.
Calibration Approach:  To calibrate these microphones, I'm using the approach shown above.  Here, I put the Tympan in my sound chamber and play known sounds at it.  I record the digital values obtained by the Tympan (recorded via its SD card) and compare them to the "truth" that was simultaneously recorded from my laboratory-grade microphone (Bruel & Kjaer 4191).

Truth Microphone:  It is important that the truth microphone be placed very close to the Tympan microphone during this calibration.  Ideally, they'll see exactly the same sound levels.  Pictures showing my arrangement is shown below.
Connecting the Tympan Microphone:  Each of the three test microphones connects to the Tympan in a different way:
  • Sony Mic:  Like many lapel microphones, this mic comes nicely packaged with a 1/8" (3.5 mm) phono plug.  We have a mic jack on the Tympan PCB just for this purpose!  I programmed the Typman to supply a 2.5V bias voltage for this microphone.  
  • PCB Mic: This microphone is just a raw element.  We designed the Tympan to have two of these mics right on the circuit board so that they'd be easy to use.  Therefore, this mic is already wired and simply needs to be enabled in the Tympan software.  
  • Knowles Mic: This is a raw hearing aid microphone.  I soldered some wires to it and connected the wires to the Tympan's "line in" holes that are on the edge of the Tympan PCB.  I provided the bias voltage from a pair of AA alkaline batteries.
Software:  For this test, I wrote an Arduino sketch that allows me to switch the Tympan between the three different microphones.  The sketch saves the digitized audio to the Teensy's SD card.  Additionally, the sketch steps through different levels of gain on the Tympan input (0 dB to +40 dB) so that I can see its effect.  My Arduino code is on my GitHub here.  You'll also need the Tympan library, which you can get here.

Example Data:  Below is a spectrogram of the audio data that I recorded during one of these calibration tests.  The top plot shows the audio from the truth microphone.  The bottom plot is the signal recorded by the Tympan, in this case for the Sony mic.  You can see that I had a loop of audio that I was playing over-and-over into the room.  The audio loop alternates between white noise and a 1 kHz test tone.  In the bottom plot, you can clearly the see the effect of increasing the gain of the Tympan input.
Analyzing the Truth Data:  I started by analyzing the truth data.  Looking at just the white noise periods, I filtered the audio into 3rd-octave bands from 125 Hz to 16 kHz and assessed the average signal level in each band.  Because this laboratory microphone is itself regularly calibrated, I know its data in units of Pascals, which leads directly to units of sound pressure level (SPL).  The SPL that I measured in each band is shown in the figure below.  This is the truth to which I will compare the Tympan data.
Analyzing the Tympan Data:  I performed the same 3rd-octave band analysis of the Tympan data.  Because this microphone is not calibrated (that's what we're doing here) I can only measure the signal levels relative to digital full scale (ie, relative to the level at which the system starts to digitally clip the data).  The plot below shows the 3rd-octave band levels that I measured for the Tympan for the five different gain settings.  The blue line at the bottom shows the levels when the input gain was set to 0 dB while the green line at the top is for an input gain of +40 dB.
Combining with the Truth:  The last step to computing the scale factor is to combine the Tympan data with the truth data.  By bringing the two sets of data together, I can compute how the Tympan digital values (dBFS) can be scaled to reveal the true, in-the-air sound pressure level (SPL).  The figure below shows the resulting scale factor for the Sony mic for the different Tympan gain settings.  It is good to see that the gain setting only appears to affect the overall sensitivity of the system -- that the shape of the frequency response is basically the same for all gain settings.

Repeat for Other Mics:  When I perform this calibration process for all of the microphones, I get the figure below.  It shows that the Sony mic (blue) has a up-sloping response, which is good for a closely-placed lapel microphone.  The PCB mic (orange) is more flat, but has nearly the same sensitivity as the Sony mic.  The most interesting response is the Knowles mic (yellow) because it is nearly 20 dB more sensitive than the other two.  That is quite a difference!
What Gain Setting to Use?  In my tests, I tried a bunch of different gain settings.  Which is the right one to use?  Well, one approach to picking the right gain is to decide what is loudest sound that is likely to be seen.  Let's assume that 120 dB SPL is the loudest sound that we want the Tympan to handle  Then, we look at our sensitivity numbers and choose a gain setting that permits this maximum SPL without clipping.  Using the data for the graph above, the calculation goes like this:

  • Sony Mic at 120 dB SPL yields a digital level of: (120-94) + -48.6 = -22.6 dBFS.  This means that it has 22.6 dB of excess headroom.  I can safely set the gain to +20 dB.
  • PCB Mic at 120 dB SPL yields a digital level of: (120-94) + -47.4 = -21.4 dBFS.  This means that it has 21.4 dB of excess headroom.  I can safely set the gain to +20 dB.
  • Knowles Mic at 120 dB SPL yields a digital level of; (120-94) + -28.9 = -2.9 dBFS.  This means that it only has 2.9 dB of headroom.  For this mic, I would leave the gain at 0 dB
We're Calibrated!  With this testing, we've now calibrated these three microphones with the Tympan.  We know the frequency response and we know how to relate our recorded digital values to real-world SPL numbers.  We also have some guidance as to what gain value we should use for each microphone.  We got a lot done!

Follow-Up:  I've added the raw data and my Matlab analysis files to my GitHub repo.  You can get them here.

Saturday, May 20, 2017

Enclosing the Electronics

After designing and building our custom electronics for the Tympan, it was clear that we needed an enclosure to hold it all together.  Using zip ties (my usual go-to solution) just wasn't good enough.  I needed something more proper to wrap around and protect the electronics.  I was kinda nervous about taking this step because, if you've never designed an enclosure before, it is HARD!  Here's a quick picture tour of how I got to a workable enclosure.  Yay pictures!
Making Something Attractive?  Normally, one wants an enclosure to be both functional and attractive.  As I started into this task, though, I very quickly learned that "attractive" is not really part of my skill set.  It's especially challenging  when the electronics (ie, the bulky guts that I'm trying to cover up with my enclosure) have already been designed and built and can't be altered.  This imposes some challenging constraints on the enclosure.  So, I set aside the goal of making it attractive and I focused on simply making it functional.

First Attempt:  Working with a fellow engineer who knows more about CAD than I do, we decided to use a two piece design that would sandwich the electronics and battery.  We'd 3D print the two pieces of the enclosure and hold the whole thing together with four small screws.  As you can see below, our first design ended up being pretty boxy.

Our first design.  Boxy!
Begin the Revisions!  Seeing it on the screen, I could begin to visualize in my brain how I might want to hold and use the device.  I decided that, if I was wear this device, I'd most likely keep it in my pants' pocket.  I decided that the boxiness of its nose would make it hard to slide into and out of my pocket.  So, we revised the design to make the bottom cover slimmer and we put big slope on the top cover.

Revising the design to make it slimmer and easier to slide down into a pocket.
Iterate, Iterate, Iterate!  With the overall configuration taking shape, we began to make lots of little changes to accommodate the battery wires, to give better access to the volume pot, and to expose the LEDs (box #3 below).  At this point, I decided that the sloping nose made it harder to get your fingers around the volume pot, so we we removed the slope (box #4).  This is the design that we used for our first 3D print.

Real-World Experience:  With the real, physical print of design #4, we were able to put it all together for the first time -- electronics plus battery plus top and bottom enclosure.  Almost immediately, I realized that I needed access to the Teensy's reset button, which was covered by our enclosure.  Oops!  So, we added a round hole to expose the reset button (see #5 above).  Then, we further expanded the hole to expose the SD card (#6 above).  Unsure if the hole was big enough, we took our 3D print of design #4 and used a dremel tool to cut the square hole (see picture below).  It wasn't pretty, but the hole worked just fine to access the SD card.
The opening to expose the SD card isn't attractive, but it does work.
Final Design.  After all of these iterations, we got to our final design, which is shown below.  The CAD files for this design are shared on the Tympan GitHub here.
Our final design.  Download it from our GitHub!
SLA vs FDM.  We printed a couple of copies of our final design using SLA.  The quality of the translucent SLA prints was fantastic, especially the surface finish.  But, the SLA prints were expensive -- too expensive to make lots of copies.  Luckily, I got hooked up with the good folks at Tangible Creative, who were able to FDM print 10 sets of enclosures for about $10 a set.  They came out pretty nicely (see picture below).  Sorry about the boring black color.  Next time I'll pick something more fun!

Fitting the Tympan electronics into the FDM-printed enclosure.
Make it Pretty!  So, while I ended up with an enclosure that does the job, it has plenty of room for improved aesthetics.  If you think that you can make it better, take our design files and make something better!  Please!

Tuesday, March 14, 2017

Tympan Electronics and Its Self-Noise

After measuring the audio performance of the Teensy Audio Board (see my previous post), I felt that I needed something better.  If I wanted my open-source hearing aid ("Tympan") to sound good, I needed a quieter audio interface with a bigger dynamic range.  So, with help from friends and colleagues, I decided that we should build our own.  Today's post gives a quick overview of its design and then I'll present some measurements of its performance.  Were we successful?  Were we able to get better dynamic range?  Let's find out...

The Audio Codec is the Heart:  The picture above shows the Tympan audio interface.  The heart of the board is the audio codec at the top-center.  An audio codec is a highly-integrated chip that, among other duties, does all of the amplification and digitization of the incoming analog audio signals.  Choosing the right codec and then properly designing the circuit board around it are both key elements to achieving a low-noise design with maximum dynamic range.

Choosing an Audio Codec:  The Teensy Audio Board uses the SGTL5000 audio codec.  Presumably it was chosen because it is small, low-cost, low-power, and has a built-in headphone driver.  For my Tympan audio interface, I want all these same features, but I also want it to be quieter.  After looking at a bunch of options, and after talking with colleagues who have experience with a variety of TI parts, we chose to go with the Texas Instruments TLV320AIC3206 (product page here).  It's got many of the same features as the SGTL5000 but promises better audio performance, though at the cost of a few extra bucks per chip.  If it gets me the wider dynamic range that I want, I'll be very happy with that trade-off.

Circuit Design:  Like with the SGTL5000 on the Teensy Audio Board, the TI 3206 needs both the I2C and I2S buses to communicate with the host processor (the host processor being a Teensy 3.5 or 3.6).  Also like the Teensy Audio Board, we will run the TI 3206 in "slave" mode, where all clocking is provided by the host processor.  In other words, our connections to the TI 3206 parallel the connections used by the SGTL5000.  Therefore, in designing our Tympan circuit, the schematic for the Teensy Audio Board was a great help.  Yay for open source!  And, to continue the sharing, our own schematic is available on the Tympan GitHub here.

Software Driver:  After laying out the PCB and getting it fabricated, we had to write software to allow the Teensy and the TI 3206 to talk to each other.  Since I wanted to fit within the Teensy Audio ecosystem, we needed to write a "AudioControl" module that configures the TI 3206 to be in the proper I2S mode so that Teensy's existing I2S functions can successfully transfer audio data to and from the codec.  Luckily, I've got a buddy (Brendan, of FlexVolt fame!) who dived in and figured it all out.  His Arduino/Teensy compatible "AudioControl" module is now on the Tympan GitHub (h-file is here, cpp file is here).  Thanks, Brendan!

Measuring the Self Noise:  Once Brendan got the software side of things working [and, in the process, finding errors in the Tympan design -- we erroneously swapped "DIN" and "DOUT" by accident!  Oops!  The schematic above has been corrected.], I turned my attention to measuring the new system's audio performance.  My primary concern was the noise floor of the new hardware.  Was it better than the Teensy Audio Board?  To find out, I used a raw 3.5 mm stereo plug in the Tympan's input jack and shorted both the left and right inputs to ground.  Now, when I start recording, I should only see the Tympan's own self-noise.

Arduino Sketch:  Now I need some software to do the actual recording.  So, starting from the Arduino sketch used to record the noise for the Teensy Audio Board (here), I swapped it over to use the Tympan audio board instead of the Teensy audio board (new version here).  This sketch digitizes the input audio (which has been shorted to ground) and sends the digital samples over USB to be recorded on the PC.

Results, USB Audio:  With the inputs shorted on my Tympan board, and with me recording the audio via USB in Audacity (as discussed here), I recorded the self-noise of the Tympan.  The spectrum of the self-noise is shown below.  It's a pretty flat spectrum, which is always nice to see.  The only unexpected feature is the increase in the noise seen at the highest frequencies.   What is that?
It's a pretty nice spectrum, except for the bump up at the high frequencies.  What's that?!?
USB vs SD:  The recording above was taken via USB.  Therefore, the USB cable was attached to the Teensy/Tympan.  USB cables are notorious for injecting noise.  Frankly, I surprised that the spectrum shown above is as low and as flat as it is.  To see if the USB connection was the cause in the bump at the higher frequencies, I revised the sketch to record the audio to the Teensy's SD card instead of sending it over USB (new sketch is here),  Re-running my test, I see that the high-frequency hump is gone!  Now that's a beautifully flat spectrum...
By disconnecting the USB cable and recording the audio via SD card, the bump in the spectrum goes away.  Now the self-noise is nice and flat.  Excellent.
Noise Floor Comparison:  My primary goal for the Tympan board was to have a lower the noise floor (and thereby increase the dynamic range) than I saw with the Teensy Audio Board.  To see if I was successful, I used my recordings to compute the total self-noise across the frequency range of 125-8000 Hz. This is the frequency range most relevant for my hearing aid work.  I assessed this broadband self-noise value for the Teensy and Tympan boards across a range of analog gain settings.  The result of this noise analysis is shown in the figure below.
Apples-to-Apples:  The Teensy and Tympan boards have different ways of specifying the input gain.  Ideally, I'd be able to set the same amount of gain for each board, but that wasn't possible.  So, to  align the data in the most fair way, you can see that plot the values as function of the "maximum allowed input signal".  As expected, increasing the gain decreases the max allowed input.  So, at any given value for max allowed input, it is a fair to compare between the two systems.  As can be seen, the Tympan audio board does indeed have lower noise than the Teensy audio board.

Dynamic Range Comparison:  Another way to express this same data is to show the dynamic range of the system.  The dynamic range is the difference between the max allowed input signal and the system's noise floor.  I want as wide a dynamic range as possible, so as to better mimic the human ear.  As can be seen below, the Tympan audio board does indeed provide greater dynamic range than the Teensy audio board.  Specifically, the Tympan is getting 92.4-94.6 dB of dynamic range (in the 125-8000 Hz band) versus 80-81 dB for the Teensy Audio Board.  This is quite an improvement!
Keeping Perspective:  While I am very pleased with the performance of the TI 3206 on the Tympan audio board, it's important to remember that the Teensy audio board has some significant advantages in other areas.  First, you can go buy your own Teensy Audio Board right now, whereas you can't (yet) get a Tympan.  Second, the Teensy Audio Board is remarkably inexpensive.  It's hard to see the Tympan board ever being that inexpensive.  Yes, PJRC did a fantastic job making a good piece of hardware at a fantastic price.  That's for sure.

Next Steps:  I'm going to use the Tympan as a platform for open source hearing aid experiments.  But, a hearing aid is more than just electronics.  So, my next steps are to start adding in other elements like microphones and earphones.  And, I have to get back to making audio processing algorithms!  That's where the fun really happens!

Sunday, March 12, 2017

Teensy Audio Board Self-Noise

When working with audio, one typically wants as quiet a system as possible -- no one likes listening to hiss.  So, when I started working with the Teensy and the Teensy Audio Board, I applied a critical ear to the board's performance.  While the Teensy Audio Board was very fun, quite easy to use, and relatively inexpensive, I found that it was noisier than I like.  In this post, I'm going to illustrate the noise levels that I recorded and I'll show a workaround that helped remove a lot of that noise.

Setup:  For these tests, I used a Teensy 3.6 attached to Teensy Audio Board.  I then wrote an Arduino sketch (shared on my GitHub here) that would record audio from the line-in and send it to both the headphone output as well as to the USB Audio output.  I recorded the digital audio coming through USB using Audacity (as discussed here).  As shown in the picture above, To try to isolate just the self-noise of the system, I shorted the inputs using a jumper across the Teensy Audio Boards line-in terminals.  This should be as quiet as it can get.

First Results:  The audio that I recorded (shared here) sounded funny to my ear.  If I turned it up, I could hear a very annoying unsteady whining noise.  Looking at the spectrum (see plot below), I could clearly see some narrowband tones starting around 2 kHz.  That's right where one's hearing is most sensitive, which makes this kind of self-noise particularly problematic.  It's definitely not what you want if you're trying to make a hearing aid type of device.  What could be the cause of this?

Disable the ADC's HP Filter:  After a bunch of messing around, I finally stumbled across this post on tthe Teensy forum.   Here, "Raj" stated that the SGTL5000 audio codec (which is at the heart of the Teensy Audio Board) has a high-pass filter in its ADC.  He said that this HP filter was introducing a lot of noise and he shared the command for disabling that filter.  When I put the command "adcHighPassFilterDisable();" into my sketch and re-ran my tests, those annoying narrowband tones in the Teensy Board's self-noise went away (audio file here).  Ahhh.  That's so much better.

Varying the Gain:  The data shown above were taken with the input gain of the Teensy board set to "10" (ie, full-scale input spans 0.56 Vpp).  There are other gain settings that one could use.  So, I repeated my measurements at other gain levels to see if the input-referred self-noise was better or worse.  The results are below.

 As can be seen, the noise with the HP filter (the blue line) is noisier in all cases than when the HP filter is disabled (orange line).  So, as long as you can handle a little DC offset in your audio data, you should definitely disable that filter.

A second finding is that the apparent (input-referred) self-noise goes down as the gain increases.  So, if you have really quiet signals that you're trying to record, turning up the gain might help reveal those signals.

Dynamic Range:  The trade-off with turning up the gain is that the maximum signal level that can be recorded without clipping also goes down as the gain is increased.  For many applications, therefore, it is just as important to look at the dynamic range for the system.  The dynamic range is the difference between the maximum input level and the noise floor.  When I run the numbers for the Teensy Audio Board, I get the results below.

Here, I see that, when the HP filter is disabled (the orange line), the Teensy Audio Board has about 81 dB of dynamic range.  And, I also see that the dynamic range is basically independent of the gain setting.

Is it Good Enough?  So now we're down to the hard question:  is 81 dB of dynamic range good enough for my needs?  Well, it is a pretty decent number, especially for the price of the Teensy Audio Board.  But, for my use as part of an open-source hearing aid, where I need to amplify quiet sounds while not distorting on already-loud sounds, I think that I need a bigger dynamic range.  Normal human hearing spans on the order of 120 dB of dynamic range.  I think that I need hardware that'll get me at least a little closer to that number.

Motivation for a New Board:  The results shown here were my motivation for building the audio interface (the "Tympan") that I introduced in my last post.  In my next post, I'll share some details of that audio interface and I'll perform these same self-noise measurements to see if I was able to get a wider dynamic range.  Making wide dynamic range systems isn't easy, so it'll be exciting to find out how I did!

Follow-Up:  I measured the self-noise and dynamic range of the new Tympan board.  It's pretty good!  If you're interested, you can see the results here.