play_sd_wav library code questions

Status
Not open for further replies.

gwideman

Well-known member
Hi all, but probably for Paul:

I've been studying the internals of play_sd_wav, and have a pretty good grasp on what it does.

However a few points are puzzling:

1. Several combinations of data rate and mono/stereo are not implemented. All the "CONVERT" ones for 22k and 11k data rates, for example.
What was the plan for implementing these? Does it involve changing the clock rate of the DAC, or was the idea to transmit the same samples twice or four times? Or perhaps interpolation?

2. Was the library intended to be able to handle WAV files that have more than one chunk of audio (ie: fmt... data ... fmt ... data)? Are such files common, and does the code succeed in such a case?

3. In the consume() code for 16-bit stereo, there are a couple of odd appearances of header[0]:

Code:
if (leftover_bytes) {
    block_left->data[block_offset] = header[0];
//PAH fix problem with left+right channels being swapped
    leftover_bytes = 0;
    goto right16;

and

Code:
if (size == 0) {
    if (data_length == 0) break;
    header[0] = (msb << 8) | lsb;
    leftover_bytes = 2;
    return false;

These appear to send a header value to the DAC, and to fetch audio data into the header variable. What is the objective here?

Illumination will be gratefully received :).
 
Wow, lots of questions. Let's see if I can get them quickly...

1. Several combinations of data rate and mono/stereo are not implemented. All the "CONVERT" ones for 22k and 11k data rates, for example.
What was the plan for implementing these?

The plan (where "plan" is a rather strong word....) is what I call "low priority". That really means it may be years until it happens, but a more likely scenario is I'll never actually get around to those.

But if someone really wants them, maybe they'll contribute a patch?


Does it involve changing the clock rate of the DAC, or was the idea to transmit the same samples twice or four times? Or perhaps interpolation?

The memory sample player does do this conversion by adding samples with linear interpolation. So far, people seem pretty happy with the results. I'd imagine that would be the way to do it for WAV files too. But if someone submitted a patch that just duplicated samples, I'd probably merge it.

Long ago I dreamed of using the crypto accelerator to do cubic spline interpolation. NXP/Freescale has an app note about repurposing the crypto unit like that, as I recall in the context of resampling power line data (not audio) to precisely match a FFT interval to avoid the need for Hanning window shaping.

Of course the best way would also include a low pass filter. But that seems like overkill, especially if linear interpolation is used, and anyone who *really* cared could just add a filter in the design tool.


2. Was the library intended to be able to handle WAV files that have more than one chunk of audio (ie: fmt... data ... fmt ... data)?

Nope.


Are such files common, and does the code succeed in such a case?

I believe you are the first to ever mention such WAV files here on this forum, and I have personally never even heard of such a feature (though it's not hard to imagine with extra RIFF chunks), so I'm going to go with "not common"...


3. In the consume() code for 16-bit stereo, there are a couple of odd appearances of header[0]:

Honestly, I don't know. Haven't really looked at that code in some time, and I've accepted at least a couple patches.

Right now I'm working on new hardware and struggling just to keep up with ordinary support and bug fixing (like 2 recently reported serial issues). I hope to work on the audio library much more next year, but I just can't put engineering time into right now.
 
Wow, lots of questions. Let's see if I can get them quickly...

.

Thanks Paul, that was very helpful, especially your thoughts on the slower data rates. And of course, it's understood you're chronically overloaded with other developments and support.

For readers following along: The "memory sample player" that Paul refers to is play_memory.h/.cpp. Its algorithm, unsurprisingly:

For 22k: Interpolate one intervening point by simply adding two successive input samples and divide by two ( >> 1).
For 11k: Same idea, but calculate three intervening points with 3:1, 2:2 and 1:3 weighting.

The only "trick" is the necessity to persist "prior last sample" across invocations of update()
 
Last edited:
Wow, lots of questions. Let's see if I can get them quickly...

Paul -- I wonder if you have example test wav files that have the "features" that necessitated the STATE_PARSE4 and STATE_PARSE5 strategies to "ignore extra unknown chunks" (presumably after fmt) and "skip past junk data before fmt header"?

I'm trying to refactor the code to make "reading the header" a separate function from "play the audio", so the PARSE states don't need to be in the update - consume function, hopefully simplifying that area.

To do so, I want to be sure I understand what problem PARSE4 and PARSE5 actually address. In particular, are they skipping over properly formatted subchunks ('size' word followed by that much data), or are they dealing with incorrectly formatted wav files.

And of course, known challenging examples would help validate an alternative approach.

Thanks -- Graham
 
Status
Not open for further replies.
Back
Top