WAV playback

55 views
Skip to first unread message

Michael Cooper

unread,
Jan 1, 2012, 7:11:47 PM1/1/12
to flysig...@googlegroups.com

Hi All—

 

Happy New Year to you all!

 

Over the past couple of days, I’ve been doing a bit of work on WAV playback for FlySight. The idea is to allow the playback of 8-bit PCM WAV files (easily created using free tools) stored on the FlySight’s disk, triggered at certain elevations. As always, I don’t think it would be a good idea to use this feature for something critical like indicating break-off/pull time, since GPS signals can be jammed. However, I do think it might be useful to indicate, for example, transition points during a jump.

 

I’ve pushed these changes to the Github server (along with a sample WAV file), but there are a couple of remaining issues that I’m hoping someone else might be able to help with. First, I’ll describe how I’ve implemented the WAV audio, and then I’ll describe the issues.

 

The WAV format is actually a container only. Strictly speaking, what we’re using here is 8-bit PCM audio stored in a WAV file. The nice thing about this format is that the stored samples are similar to what is currently stored in the sine table in Tone.c. By creating a WAV file with the same sample rate as the FlySight uses (31250 Hz), we can simply load each sample into the OCR1 registers, as we do with tones, and as a result the file is played back as FlySight’s output.

 

Because we have a limited amount of memory to work with, I’ve implemented a double buffering scheme with two 256 byte buffers (really one circular 512 byte buffer, but each half is read in turn). At a sample rate of 31250 Hz, this means we need to read into one half of the buffer every 8 ms or so.

 

The need for a read from disk is signaled when the TIMER1 ISR begins reading the left/right half of the buffer. However, the actual read is carried out in a “task” called by the main loop—similar to the way we’re currently handling data from the u-blox module. This is a pretty typical way of doing things—it’s bad form to do too much in an ISR, since it ties up the entire system. However, it does mean that Tone_Task() needs to be called at least every 8 ms.

 

In testing, I get good quality audio as long as logging has not begun. However, when logging begins (i.e., when the green light starts flashing), the sound becomes artifacted. I think this is a result of Tone_Task() being called too late, so that old data is repeated before new data is loaded. I’ve tested a couple of hypotheses on what’s causing the slowdown:

 

1.       Writing the log to disk. I don’t think this is it. If I comment out just the f_write commands in Log.c, the artifacting is mostly unchanged.

2.       Flushing the log file. Again, if I comment this out, the artifacts remain.

3.       The calls to Log_WriteInt32 etc. Once again, if just these calls are commented out, the artifacts are reduced, but still there.

4.       Finally, if I comment out the call to UBX_HandleTimeUTC, the artifacts do disappear completely. However, I wonder if this is just because we’re working very close to a performance limit, and removing a couple of heavy tasks (regardless of what they are) solves the problem.

 

I’ve been trying to think of how to improve performance, either in the newly-added code or in other parts of the firmware, but am having troubles coming up with viable solutions. The audio buffer is about as big as it can be, since we’re pushing up against the 4K SRAM capacity of the AT90USB646—the processor used in most FlySights. A couple of solutions seem like possibilities:

 

1.       Reduce the time spent in ISRs.

2.       Break up the UBX_Task into smaller tasks which can be interleaved with calls to Tone_Task.

 

I’m leery of using a solution which just comes in under the wire, since it won’t leave much room, e.g., for Luke’s FlyBlind firmware to incorporate the PCM audio additions.

 

To reproduce my tests, you’ll need to grab the latest beta firmware from Github. This includes the PCM functions (in Tone.h) as well as a “test.wav” file which can be copied to the root folder on your FlySight. In Main.c, you’ll find that I’ve added Tone_Task to the loop, but have commented out the call to Tone_Play just before the loop. If you uncomment this line and install the firmware on your FlySight, you should hear the audio file played when you turn the unit on. Artifacting is only apparent if you allow the FlySight to warm up for a few minutes and then cycle the power, so that it gets a fix before the initial call to Tone_Play is complete.

 

Any feedback would be greatly appreciated. Thanks!

 

Michael

Reply all
Reply to author
Forward
0 new messages