
Originally Posted by
PaulStoffregen
Only 9 us is a suspiciously low time for a SD card sector read. Are sure you're really capturing a representative sample of the actual times? Would be much better to compute the min, average and max times and print those 3 numbers. As I understand this code, it seems you're printing only a single measurement every 200th run and ignoring everything that happens in the other 199 cases. A min/avg/max report covering all 200 would show a clearer picture of what's really happening.
On the slow performance, it the SD card has to fetch another sector, and especially if a FAT sector needs to be read as well as a data sector, you can expect the operation to take some time.
One thing you might try if you're using the SD card by SPI (not the builtin SD socket on Teensy 3.6) is the experimental SD optimizations. Edit SD_t3.h to enable that code. It caches several sectors. But it was written before Teensy 3.6 and 4.0, so it only supports SPI access to the card. It's also read-only, which is most of the reason it's considered experimental. But it's really useful to compare against the default SD library code if you're seeing performance issues.
Hi Paul, thank you for your answer; I started adding some lines in order to get min, max and average times, and the result was so strange (for me!), that I decided to see each value; this is my code, normal speed playback:
Code:
void AudioPlaySdRawMod::update(void)
{
t = micros();
rawfile.seek(x);
n = rawfile.read(basket, AUDIO_BLOCK_SAMPLES * 2);
for (i = n/2; i < AUDIO_BLOCK_SAMPLES; i++)
basket[i] = 0;
x += AUDIO_BLOCK_SAMPLES * 2; // uint32_t x, defined in header
for(i = 0; i < AUDIO_BLOCK_SAMPLES; i++)
block->data[i] = basket [i];
t_array[blocks] = micros() - t; // uint16_t t_array[256], defined in header
transmit(block);
blocks ++; // uint32_t blocks, defined in header
if (blocks == 1000)
{
for(i = 0; i < 1000; i++)
{
Serial.print(i);
Serial.print(" ");
Serial.println(t_array[i]);
}
Serial.println();
Serial.println();
Serial.println();
blocks = 0;
}
}
else
{
rawfile.close();
AudioStopUsingSPI();
playing = false;
}
release(block);
}
and this is the result:
Code:
0 211
1 7
2 210
3 7
4 212
5 7
6 212
7 8
8 212
9 7
10 212
11 7
12 211
13 7
14 211
15 7
16 213
17 7
18 213
19 8
20 2138
21 7
22 212
23 7
24 211
25 8
26 211
27 8
28 213
29 7
30 213
... and so on
Using the following code (playback at double speed):
Code:
void AudioPlaySdRawMod::update(void)
{
t = micros();
rawfile.seek(x);
n = rawfile.read(basket, AUDIO_BLOCK_SAMPLES * 4);
for (i = n/2; i < AUDIO_BLOCK_SAMPLES; i++)
basket[i] = 0;
x += AUDIO_BLOCK_SAMPLES * 4; // uint32_t x, defined in header
for(i = 0; i < AUDIO_BLOCK_SAMPLES; i++)
block->data[i] = basket [2 * i];
t_array[blocks] = micros() - t; // uint16_t t_array[256], defined in header
transmit(block);
blocks ++; // uint32_t blocks, defined in header
if (blocks == 1000)
{
for(i = 0; i < 1000; i++)
{
Serial.print(i);
Serial.print(" ");
Serial.println(t_array[i]);
}
Serial.println();
Serial.println();
Serial.println();
blocks = 0;
}
}
else
{
rawfile.close();
AudioStopUsingSPI();
playing = false;
}
release(block);
}
the output is more uniform:
Code:
0 211
1 211
2 211
3 212
4 211
5 211
6 211
7 211
8 211
9 214
10 210
11 213
12 213
13 212
14 213
15 213
16 212
17 213
18 213
19 212
20 212
21 211
22 210
23 213
24 213
25 212
26 212
27 213
28 216
29 213
30 213
... and so on
All these tests have been done with a Sandisk ultra 32GB not recently formatted: tomorrow I'll do a deep format and will repeat all tests.
About trying SD_t3.h I belive this a bit too difficult for me; at this point I think I'll make a small PCB with a ground-plane for W25Q256, to be mounted on the Audio board, than see what happens.