Playing audio from SD whilst main loop is accessing different file on SD

Status
Not open for further replies.

stumcconnel

New member
Hi folks,

I'm still getting used to finding my way around the documentation and codebase here and am getting myself into a bit of a muddle, so I'm looking for some advice please.
I have a Teensy 3.6 running a loop that reads chunks of binary data from an SD card. Depending on the data packet type, the loop can read anything between 13 bytes which are then immediately blitted to an I2C LED matrix, up to around 1600 bytes which are expanded out to 32KB and stuffed into a frame buffer which is then dealt with asynchronously by DMA to drive an SPI TFT display.
Each packet is timestamped in milliseconds, so the loop spends the rest of the time waiting to reach the required time before updating that LED matrix or TFT display.
The LED matrix is updated every 17mS or so and the TFT frame buffer is updated no faster than 10 times a second, but usually only once every few seconds.

I want to add two other cases into the loop though (cases 1 and 2 in switch statement) to play audio files stored on the SD card, on two mixer channels.
These are 11025Hz, 16bit mono PCM wav files, so pretty low bitrate, but can range from anywhere from a few KB to 5MB. There can be over 50MB worth of files in total so that kinda rules out using SPI flash storage.

The longer ones are typically backing tracks and the short ones are overlaid sound effects, hence why I want the mixer arrangement.

I've started testing by using this mixer setup:
Code:
AudioPlaySdWav           playWav1;
AudioOutputAnalog        audioOutput;
AudioMixer4              mixer1;
AudioConnection          patchCord1(playWav1, 0, mixer1, 0);
AudioConnection          patchCord2(mixer1, audioOutput);

And then using playFile() to play one of the test files I found around here (my 11025Hz files don't work but I'll worry about that later).
The audio starts playing fine, but then when I start reading my other data file, the audio stops and so does the data file reading.

I know that multiple SD file handles can be dealt with because I tried using another handle to read 1KB chunks of raw data from the wav file and just spit some of it out the serial port at the end of every loop iteration. Perhaps it's the threaded SD access? (I believe playFile() is interrupt driven?)

Does anyone have any suggestions on which angle to attack this from? I'm considering just manually reading the wav files on an interrupt cycle and throwing data at the DAC output, but I just feel that it must be possible using the existing libraries, having seen some of the impressive stuff people are doing with them.

Any help would be hugely appreciated. I've attached the main loop of my code below, stripped down for brevity.
Thanks in advance!

Stu

Code:
unsigned long test()
{
	AudioMemory(12);

	unsigned long start = micros();

	Serial.print("Initialising SD card...");
	if (!SD.begin(chipSelect))
	{
		Serial.println("initialisation failed!");
		return false;
	}
	Serial.println("initialisation done.");
	
	playFile("SDTEST2.WAV");  // filenames are always uppercase 8.3 format

	dataFile = SD.open("data.bin");
	
	if (dataFile)
	{
		Serial.println("data.bin");

		while (dataFile.available() && !exit)
		{
			dataFile.read(&buf, 5);               			// packet type and timestamp
			timeStamp = *(uint32_t*)(buf + 1);

			while ((micros() - start) <= timeStamp * 1000)	// spends a lot of time waiting here
				;

			switch (buf[0])
			{
				// wav format is 11025Hz, 16bps, mono, PCM
			case 1:                             // sound type 1
			case 2:                             // sound type 2
				dataFile.read(&buf, 4);         // get sound file name from dataFile

				// play sounds file in one of two mixer channels
				
				break;

			case 3:                             // TFT data packet
			{
				// reads ~1600 bytes from SD card
				// lightly processes buffer and spits output into display buffer
				// Display is handled by DMA
			}

			case 4:										// LED matrix array
				dataFile.read(&matrixBuf, 8);           // read 8 bytes from SD
				matrixWriteDisplay();					// and blits 16 bytes to LED matrix
				break;
			}
		}
		dataFile.close();
	}
	return micros() - start;
}

void playFile(const char *filename)
{
	Serial.print("Playing file: ");
	Serial.println(filename);

	// Start playing the file.  This sketch continues to
	// run while the file plays.
	playWav1.play(filename);

	// A brief delay for the library read WAV info
	delay(5);

	// Simply wait for the file to finish playing.
	//while (playWav1.isPlaying()) {
	//}
}
 
Status
Not open for further replies.
Back
Top