Getting the best performance with SD cards and the audio library

Status
Not open for further replies.

unicornpower

Well-known member
I've written an audio looper for Teensy 3.5/6 which I use live (link below). It uses the inbuilt SD card slot to read write audio and generally works well, but I have issues getting consistent write performance out of the SD cards I'm using (SanDisk or Kingston), and I'm also finding the SD library fails to read the more recent 64GB cards I have (SD.begin() fails).

The issue I have is that most writes of 2 audio blocks (512 bytes) to the SD card takes around 2.5ms, but occasionally it will take around 150ms! This basically blows my buffering system, and means the looper runs out of blocks to play. Leading to horrible glitching.

My questions are:

1. Is there another version of the SD library that is compatible with the Teensy audio library that provides improved write performance?
2. Is there a reason I'm unable to read 64GB SanDisk Extreme cards (is this a FAT issue?), can I resolve this with the standard library?
3. The SDFat library has a way to enable Exclusive SPI mode, which it says yields superior performance, is there a way to achieve this with a library that's compatible with the Teensy audio library?

I'm wanting to use the looper for an imminent performance, so any help would be highly appreciated!

Thanks,
Scott

https://github.com/cutlasses/Looper
https://youtu.be/Ur3xYh8PTQg
 
Last edited:
In terms of #2, SD cards and micro-SD cards above 32 gigabytes are SD-XC cards (1-32GB are SD-HC cards). Generally, above 32 gigabytes, the VFAT filesystem is not used. Instead a new filesystem (exFat) is typically used.

So I suspect, the simplest way forward is to downsize to 32GB cards. I have used 32GB cards (both Samsung and SanDisk) in my Teensys, though I typically don't use all that much space.

There is an alternative SD library (SdFat-beta), but as I recall that has some issues, and I don't think it is compatible with the Audio library.

At one point a few months ago, Paul was mentioning that in the future, you would be able to add other filesystems other than vanilla VFAT in the audio, but I don't recall hearing much about this recently. In particular, this would be useful for the Teensy 4.1 which can have a flash memory chip soldered to the Teensy, and the preferred filesystem is SPIFFS. I looked at the 1.54 beta announcements, and I didn't see anything about it there.

I don't know if the Teensy 3.5/3.6/4.1 micro SD drives are capable of supporting SD-XC cards or not.
 
Thanks for the info, Michael. I actually only bought the 64GB cards because they boast the fastest speeds so I thought it might alleviate my write time issue. I definitely don't need to record 64GB of audio! :)

Yeah, I had a look at SDFat-beta. I couldn't get it compiling with the audio library (like you say), and didn't want to spend too much time on it, as I have no idea if it will help with my problem. I kind of assumed that if it was easy to get it working with the audio library Paul would have already done it!

Do you happen to know if it's normal to see such massive inconsistencies in write times (e.g some writes taking x10 longer than others). I'm not sure if this is some internal caching in the lib (flushing doesn't seem to improve matters), or the nature of the card (or possibly a bit of both). Are there any SD cards that are known for more consistent read/write times?
 
I, too, have seem massive variation in write times to the SD card. It seems to depend a lot on the SD card itself. It is also affected by how they are formatted.

So, after a bunch of experiments with my T3.6 back in 2018, I settled on the following configuration:

* I use the Greiman SD Library. I did my experiments before Teensy 4 existed, so I was using the old SdFat. I don't know if the T4-compatible version of the Greiman library is as good as the old one, but the old one was much better than the default Arduino one.

* Using the Greiman library at the core, I then wrote my own SD writing classes to more easily interface the Greiman stuff ot the Audio-library approach used by the Teensy. My classes allowed for a lot of buffering (using Audio blocks) to smooth over variability in the SD card's write speed. This all lives in my Tympan_Library, which is nominally for my T3.6-based Tympan hardware, but should work for any T3.5 or T3.6. See AudioSDWriter and its parent classes within the library.

* I settled on SanDisk Ultra cards, as they gave the best performance in my testing of the 6-8 old and new SD cards that I happened to own.

* Using the official SD formatting tool seemed to help. Reformatting periodically also seems to help.

As an example of the kind of results that I was seeing for SD Write variability, see the figure below.

ExampleSDWriting.png

After a few minutes of recording audio at 96 kHz, my mean write time was only 0.033msec but my longest SD write time was 49 msec. Huge spread. Because my library allows for a lot of buffering (when needed), none of this variability caused any write problems.

This variability in SD performance is a real pain. For sure.

Chip
 
Thanks chipaudette, that's super helpful! Sounds like you've experienced some very similar problems. Although your max write time seem much lower than what I'm experiencing. (My max write time was 150msec). I currently always write 2 audio blocks at a time (as the example code suggests this yields better performance to write in 512 byte blocks) but maybe I should try writing single 256 byte block. I'm also using SanDisk, and using the SD formatter. I find it's hard to make sure you always get genuine cards!

I have some questions if you don't mind?

1. How many bytes did you write in single 'chunk'
2. Did you have many problems using SD Fat with the audio library other than just getting it to compile? EDIT - I see you created your own fork.
3. Did you find SD Fat considerably faster/gave more consistent write times?
4. Did you use the 'exclusive SPI' mode of SD Fat, and did that yield big gains?

Thanks in advance!
Scott
 
Last edited:
If you are writing to WAV files, it won't help writing 512 bytes at a time because what is getting in your way is the 44 byte WAV header which offsets everything you write.
I have found a way around this is to open the file and write a (512-44) = 468 byte block of zeros. Subsequent writes of 512 bytes will now occur on a 512-byte boundary and should improve the throughput.

Pete
 
If you are writing to WAV files, it won't help writing 512 bytes at a time because what is getting in your way is the 44 byte WAV header which offsets everything you write.
I have found a way around this is to open the file and write a (512-44) = 468 byte block of zeros. Subsequent writes of 512 bytes will now occur on a 512-byte boundary and should improve the throughput.

Pete

I simply added a new wav header chunk to extend the wav header from 44 to 512 bytes. This chunk could hold also additional meta data. only problem could be that added chunk must be properly interpreted by reading program. If you only use your own program to read wav file skipping 512-44 zero bytes is an option.
 
Status
Not open for further replies.
Back
Top