vindar
Well-known member
Hi,
While investigating a bug report in my library, I think I found a small bug in the AudioPlaySdWav object of the Audio library.
Setup
Problem/explanation
Using SPI0 can make the sound played from the builtin SD glitch. This is because the AudioPlaySdWav object calls AudioStartUsingSPI() which itself is hardcoded to SPI0 (by calling SPI.usingInterrupt()). This means that in between a `SPI.beginTransaction()` and a `SPI.endTransaction()`, the audio library "thinks" it cannot access the SD card and this causes trouble whenever the transaction is longer that the data buffered from the SD. Indeed, by commenting away the "SPI.usingInterrupt(IRQ_SOFTWARE)" lines in Audio/spi_interrupt.h the problem goes away. The solution should be to modify the AudioStartUsingSPI() function so that it always uses the correct SPI bus (and not always SPI0) but I do not know the inner working of the library well enough to suggest a fix (who else calls this function...).
Code to reproduce the bug (adapted from "Part_1_03_Playing_Music" of the Audio examples)
While investigating a bug report in my library, I think I found a small bug in the AudioPlaySdWav object of the Audio library.
Setup
- Teensy 4.1 with the Audio Shield (rev D2 in my case)
- an SD card inserted in the builtin SD slot of the T4.1 (not the SD slot of the audio shield !).
- A device connected on SPI0 (e.g. a display).
Problem/explanation
Using SPI0 can make the sound played from the builtin SD glitch. This is because the AudioPlaySdWav object calls AudioStartUsingSPI() which itself is hardcoded to SPI0 (by calling SPI.usingInterrupt()). This means that in between a `SPI.beginTransaction()` and a `SPI.endTransaction()`, the audio library "thinks" it cannot access the SD card and this causes trouble whenever the transaction is longer that the data buffered from the SD. Indeed, by commenting away the "SPI.usingInterrupt(IRQ_SOFTWARE)" lines in Audio/spi_interrupt.h the problem goes away. The solution should be to modify the AudioStartUsingSPI() function so that it always uses the correct SPI bus (and not always SPI0) but I do not know the inner working of the library well enough to suggest a fix (who else calls this function...).
Code to reproduce the bug (adapted from "Part_1_03_Playing_Music" of the Audio examples)
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
AudioPlaySdWav playSdWav1;
AudioOutputI2S i2s1;
AudioConnection patchCord1(playSdWav1, 0, i2s1, 0);
AudioConnection patchCord2(playSdWav1, 1, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
// Use these with the Teensy 3.5 & 3.6 & 4.1 SD card
#define SDCARD_CS_PIN BUILTIN_SDCARD
#define SDCARD_MOSI_PIN 11 // not actually used
#define SDCARD_SCK_PIN 13 // not actually used
void setup() {
Serial.begin(9600);
AudioMemory(8);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
if (!(SD.begin(SDCARD_CS_PIN))) {
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
// we will use SPI0 which is free because the audio library will uses the SD builtin SPI bus...
// Normally, the audio library should never touch the SPI0 object...
SPI.begin();
delay(1000);
}
void loop()
{
if (playSdWav1.isPlaying() == false)
{
Serial.println("Start playing");
playSdWav1.play("SDTEST2.WAV");
delay(10); // wait for library to parse WAV info
}
// send dummy data via SPI0
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE1));
const int transfer_len = 2000; /// *** Sound problems appears for larges values (e.g. > 1000)
for(int i=0; i < transfer_len; i++)
{
SPI.transfer(0);
}
SPI.endTransaction();
}