Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stops playing MP3s on T4.1 #23

Open
stg opened this issue Dec 7, 2023 · 3 comments
Open

Stops playing MP3s on T4.1 #23

stg opened this issue Dec 7, 2023 · 3 comments

Comments

@stg
Copy link

stg commented Dec 7, 2023

On Teensy 4.1, at seemingly random intervals a few to a few tens of minutes apart, the MP3 player just stops playing.

What I know and have tried:

Tried a few different MP3-files and two different SD-cards - no change.

Ported the library to directly use SdFat instead of going via Arduino SD - no change.

To verify the SD card and filesystem code I set up a loop to continuously read and checksum the file over several hours:

  • Reading at full speed - works fine.
  • Reading at a slowed pace, similar to that of audio playback - works fine.
  • Reading random-length chunks of the file - works fine.

The Teensy Audio system is still running; other sources continue playing.

Calling another .play() gets the MP3Player going just fine again.

When the problem occurs, _fposition of the CodecFile class just sits there without changing, but I haven't taken any further plunges into the code - wanted to ask for ideas or suggestions first.

Got any? :)

@FrankBoesing
Copy link
Owner

I am not aware of this problem, it does not happen to me and I have not heard of it from any other user.

Theoretically, this can happen if
a) too few audio blocks are available,
b) the Teensy is too often busy with other (higher prio?) interrupts, or
c) other things are being read from the SD card at the same time.

Hope ist helps,
Frank

@stg
Copy link
Author

stg commented Dec 8, 2023

First off, thanks heaps for the quick reply!

Indeed, this does not happen when only running the MP3 player.

Audio blocks, as in AudioMemory? 32.
Update: I've checked AudioMemoryUsageMax() - never seen above 2.

No other SD-card access is done - the MP3 player reigns supreme.

This firmware does have some very high-priority (0) interrupts running though, as suggested.
Although all interrupts at or below (higher prio) that of the audio system occupy less than 5% of CPU time they may sometimes correlate in time, leading to a chained interrupt event of up to approximately 250µS.

Perhaps I should also mention that I am not running the card off the SDIO interface, but SPI1 at 16MHz.
I have, however, determined that a stand-alone sketch still works fine when running off plain SHARED_SPI, although SPI instead of SPI1.

So, if this can theoretically happen under these circumstances, could you point me in the direction of exactly what, theoretically, it is that would happen? :)

Any suggestion on overcoming this would be highly appreciated.
I have heaps of memory and CPU time to spare still, so I could certainly amp up buffer sizes for example.
Sadly, I can't amp up the priority of the PIT since the higher priority interrupts are just that for good reason.
Stuttering would of course be much preferable to plain stopping without notification (.isPlaying returns true, still).

Fantastic library, by the way.
Been much appreciated in my prototyping work.

@stg
Copy link
Author

stg commented Dec 9, 2023

In my quest to make my thingy work all good 'n stuff; I found a racing condition that, while not the cause of my problems, is something that I think might warrant a fix.

In ::stop() the buffers are free()'d and set to NULL.

If an audio interrupt occurs between these two events, the interrupt will be working with buffers that point to memory that is no longer "owned". The chance of this causing a problem is very low, but could happen and would likely be a major headache to troubleshoot since it could have rare and asymptomatic effects - the worst kinds of bugs to squash.

For example, if another interrupt occurs, which allocates memory previously used by the now free()'d buffers, and then chains into the audio interrupt, then the audio interrupt will overwrite memory that is now allocated by someone else.

Unless I am missing something ::update() should probably also check if the buffers are allocated since it won't be stopped by NVIC_DISABLE_IRQ(IRQ_AUDIOCODEC); and may as such keep working with free()'d buffers (or even NULL'd ones!) if any data happens to be left over from a previous decodeMp3(). Zeroing decoded_length[n] at ::stop() might also be a good idea for the same reason.

Anyways, if a check is inserted into ::update() (added hMP3Decoder and sd_buf for good measure):

	//got everything ?
	if(!buf[0] || !buf[1] || !hMP3Decoder || !sd_buf) return;

Then the problem can be solved in ::stop() in two ways:

  1. make a temp copy of both buf[n] pointers, set both buf[n] to NULL, then free() using the temp copy
  2. disable interrupts to make these two lines atomic

For this to work under all conditions, buf pointers should also be made volatile for option 2, or use a memory barrier for option 1.

Look, it's late, it's Friday, and I'm all full of Old No. 7; so I might be wrong about some of this... but I sure did get the occasional crash and reboot during stress-testing with really short MP3s until I secured those buffers.

I've managed to get things working by replacing the lower-than-audio-priority chained software interrupt for decodeMp3 and calling decodeMp3() directly from ::update(). I understand the logic behind this, and clearly see that this is not a great solution; but it seems to work for the time being.

But, for good measure, I went back to the original code and inserted counters in ::update() and decodeMp3(). It just stopped again and I can verify my suspicion that triggering IRQ_Reserved1 stops happening for as-of-yet unknown reasons - that is ::update() is still counting up, but decodeMp3() is not getting run any longer. Hmm... if only I could get my debugger in there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants