Hi there,
I've adapted the ResamplingSdReader from @Moo to the serial flash raw player,
it works but with 8 players running I'm getting very high values when measuring the CPU with AudioProcessorUsageMax(), using teensy 4.1 btw,
any suggestion about how to reduce the CPU load?

here's the code:
play_serialflash_raw2.h
Code:
#ifndef play_serial_raw2_h_
#define play_serial_raw2_h_

#include "Arduino.h"
#include <AudioStream.h>
#include <SerialFlash.h>

#include "stdint.h"
#include "ResamplingFlashReader.h"

class AudioPlaySerialflashRaw2 : public AudioStream
{
public:
	AudioPlaySerialflashRaw2(void) : 
		AudioStream(0, NULL),
		rawReader()
		{ 
			begin(); 
		}

	void begin(void);
	bool play(const char *filename);
	void stop(void);
	bool isPlaying(void) { return playing; }
	uint32_t positionMillis(void);
	uint32_t lengthMillis(void);
	virtual void update(void);

	void setPlaybackRate(float f) {
        rawReader.setPlaybackRate(f);
    }

    float playbackRate(float f) {
        return rawReader.playbackRate();
    }

    bool interpolationEnabled() {
        return rawReader.interpolationEnabled();
    }

    void setInterpolationEnabled(bool enableInterpolation) {
        rawReader.setInterpolationEnabled(enableInterpolation);
    }

private:

	uint32_t file_size;
	volatile uint32_t file_offset;
	volatile bool playing;

	ResamplingFlashReader rawReader;
};

#endif
play_serialflash_raw2.cpp
Code:
#include <Arduino.h>
#include "play_serialflash_raw2.h"
#include "spi_interrupt.h"


void AudioPlaySerialflashRaw2::begin(void)
{
	playing = false;
	file_offset = 0;
	file_size = 0;
}

bool AudioPlaySerialflashRaw2::play(const char *filename)
{
	stop();
    playing = rawReader.play(filename);
    return playing;
}

void AudioPlaySerialflashRaw2::stop(void)
{
	rawReader.stop();
}

void AudioPlaySerialflashRaw2::update(void)
{
	unsigned int i, n;
	audio_block_t *block;

	// only update if we're playing
	if (!playing) return;

	// allocate the audio blocks to transmit
	block = allocate();
	if (block == NULL) return;

	if (rawReader.available()) {
		// we can read more data from the file...
		n = rawReader.read(block->data, AUDIO_BLOCK_SAMPLES*2);
		file_offset += n;
		for (i=n/2; i < AUDIO_BLOCK_SAMPLES; i++) {
			block->data[i] = 0;
		}
		transmit(block);
	} else {
		rawReader.close();
		AudioStopUsingSPI();
		playing = false;
		//Serial.println("Finished playing sample");		//TODO
	}
	release(block);
}

#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592

uint32_t AudioPlaySerialflashRaw2::positionMillis(void)
{
	return ((uint64_t)file_offset * B2M) >> 32;
}

uint32_t AudioPlaySerialflashRaw2::lengthMillis(void)
{
	return ((uint64_t)file_size * B2M) >> 32;
}
resamplingFlashReader.h
Code:
#ifndef TEENSYAUDIOLIBRARY_RESAMPLINGFLASHREADER_H
#define TEENSYAUDIOLIBRARY_RESAMPLINGFLASHREADER_H

#include "stdint.h"
#include <SD.h>
#include <SerialFlash.h>
#include <AudioStream.h>

#include "../spi_interrupt.h"

const unsigned int ResamplingFlashReader_NUM_BUFFERS = 4;

class ResamplingFlashReader {
public:
    ResamplingFlashReader() {

        for (uint i=0; i<ResamplingFlashReader_NUM_BUFFERS; i++ ) {
            _buffers[i] = NULL;
        }
    }
    void begin(void);
    bool play(const char *filename);
    void stop(void);
    bool isPlaying(void) { return _playing; }

    int read(void *buf, uint16_t nbyte);
    bool readNextValue(int16_t *value);

    void setPlaybackRate(double f) {
        _playbackRate = f;
    }

    float playbackRate() {
        return _playbackRate;
    }

    int available(void);

    void close(void);

    bool interpolationEnabled() {
        return _enable_interpolation;
    }

    void setInterpolationEnabled(bool enableInterpolation) {
        _enable_interpolation = enableInterpolation;
    }

private:
    volatile bool _playing = false;
    volatile uint32_t _file_offset;
    volatile int32_t _last_read_offset = 0;

    bool _enable_interpolation = true;
    uint32_t _file_size;
    double _playbackRate = 1.0;
    double _remainder = 0.0;

    uint _bufferPosition = 0;

    int16_t *_buffers[AUDIO_BLOCK_SAMPLES];
    unsigned int _bufferLength[ResamplingFlashReader_NUM_BUFFERS];
    bool bufferIsAvailableForRead[ResamplingFlashReader_NUM_BUFFERS];

    volatile signed char _readBuffer = -1;
    volatile signed char _playBuffer = -1;
    signed char _numBuffers = 0;
    SerialFlashFile _file;

    void updateBuffers(void);
    bool isInRange(void);

};


#endif //TEENSYAUDIOLIBRARY_RESAMPLINGSDREADER_H
resamplingFlashReader.cpp
Code:
#include "ResamplingFlashReader.h"

int ResamplingFlashReader::read(void *buf, uint16_t nbyte) {
    if (!_playing) return 0;

    unsigned int count = 0;
    int16_t *index = (int16_t*)buf;
    for (int i=0; i< nbyte/2; i++) {

        if (readNextValue(index))
            count+=2;
        else
            return count;

        index++;
    }
    return count;
}

bool ResamplingFlashReader::readNextValue(int16_t *value) {

    if (_bufferLength[_playBuffer] == 0)
        return false;

    if (_playbackRate > 0 ) {
        //forward playback

        if (_numBuffers == 1 && _last_read_offset + _bufferPosition > _file_size)
            return false;

        //Serial.printf("readNextValue: %d/%d \n", _bufferPosition, _bufferLength[_playBuffer]);

        if (_bufferPosition >= _bufferLength[_playBuffer]) {
            bufferIsAvailableForRead[_playBuffer] = true;
            //Serial.printf("\ndiscard buffer: %d\n", _playBuffer);

            if (_numBuffers ==1 && _file_offset >= _file_size)
                return false;

            _numBuffers--;
            //Serial.printf("num  buffers: %d\n", _numBuffers);

            if (_playBuffer < _numBuffers) {
                _readBuffer = _playBuffer;
                //Serial.printf("switch read buffer to: %d\n", _readBuffer);
            }

            _bufferPosition -= _bufferLength[_playBuffer];

            _playBuffer++;
            if (_playBuffer >= ResamplingFlashReader_NUM_BUFFERS) {
                _playBuffer = 0;
            }
            //Serial.printf("switch play buffer to: %d\n", _playBuffer);
            updateBuffers();
        }
    } else if (_playbackRate < 0) {

        if (_numBuffers == 1)
            if (_file_offset + (AUDIO_BLOCK_SAMPLES * 2) + _bufferPosition < 0)
                return false;

        // reverse playback
        if (_bufferPosition < 0) {

            if (_numBuffers == 0)
                return false;

            bufferIsAvailableForRead[_playBuffer] = true;
            _readBuffer = _playBuffer;

            _numBuffers--;

            _playBuffer ++;
            if (_playBuffer >= ResamplingFlashReader_NUM_BUFFERS) {
                _playBuffer = 0;
            }

            _bufferPosition += _bufferLength[_playBuffer];
            updateBuffers();

        } else if (_bufferPosition > (AUDIO_BLOCK_SAMPLES-1) * 2) {
            _bufferPosition = (AUDIO_BLOCK_SAMPLES-1) * 2;
        }
    }
    int16_t *_buffer = _buffers[_playBuffer];
    int16_t result = _buffer[_bufferPosition/2];
    //Serial.printf("r: %d,", result);

    if (_enable_interpolation) {
        if (_remainder != 0.0) {
            if (_playbackRate > 0.0) {
                int16_t next;
                if (_bufferPosition < _bufferLength[_playBuffer]-2) {
                    next =_buffer[(_bufferPosition/2)+1];
                } else {
                    int nextPlayBuffer = _playBuffer == ResamplingFlashReader_NUM_BUFFERS - 1? 0 : _playBuffer+1;

                    if (_last_read_offset + _bufferPosition < _file_size-2) // second interpolation point is before the end of the file, don't int
                        next = _buffers[nextPlayBuffer][0];
                    else
                        next = result; // dont interpolate past the end of the file
                }
                int16_t interpolated = static_cast<int16_t>( (((1-_remainder) * 1000.0 * result) + (_remainder * 1000.0 * next)) / 1000.0 );
                result = interpolated;
            } else if (_playbackRate < 0.0) {
                int16_t prev;
                if (_bufferPosition >= 2) {
                    prev = _buffer[(_bufferPosition/2)-1];
                } else {
                    if (_file_offset > 2) {
                        int nextPlayBuffer = _playBuffer == ResamplingFlashReader_NUM_BUFFERS - 1 ? 0 : _playBuffer + 1;
                        int nextBufLength = _bufferLength[nextPlayBuffer] / 2;
                        prev = _buffers[nextPlayBuffer][nextBufLength - 1];
                    } else
                        prev = result;
                }
                int16_t interpolated = static_cast<int16_t>( (((1 + _remainder) * 1000.0 * result) + (-_remainder * 1000.0 * prev)) / 1000.0 );
                result = interpolated;
            }
        }
    }

    _remainder += _playbackRate;

    auto delta = static_cast<signed int>(_remainder);
    _remainder -= static_cast<double>(delta);

    _bufferPosition += 2 * delta;
    *value = result;
    return true;
}

void ResamplingFlashReader::begin(void)
{
    _playing = false;
    _file_offset = 0;
    _file_size = 0;
}

bool ResamplingFlashReader::play(const char *filename)
{
    stop();

    AudioStartUsingSPI();
    __disable_irq();
    _file = SerialFlash.open(filename);
    __enable_irq();

    if (!_file) {
        AudioStopUsingSPI();
        return false;
    }

    __disable_irq();
    _file_size = _file.size();
    __enable_irq();

    if (_playbackRate < 0) {
        // reverse playback - forward _file_offset to last audio block in file
        _file_offset = _file_size - AUDIO_BLOCK_SAMPLES * 2;
    } else {
        // forward playabck - set _file_offset to first audio block in file
        _file_offset = 0;
    }


    for (char i=0; i<ResamplingFlashReader_NUM_BUFFERS; i++ ) {
        _buffers[i] = (int16_t*)malloc( AUDIO_BLOCK_SAMPLES * 2);
        bufferIsAvailableForRead[i] = true;

    }
    _readBuffer = 0;
    _numBuffers = 0;
    updateBuffers();
    _playBuffer = 0;
    if (_numBuffers == 0)
        return false;

    _playing = true;

    if (_playbackRate < 0) {
        _bufferPosition = _bufferLength[_playBuffer]-2;
    }

    return true;
}

void ResamplingFlashReader::stop()
{
    __disable_irq();
    if (_playing) {
        _playing = false;
        __enable_irq();
        _file.close();
        AudioStopUsingSPI();
        //StopUsingSPI();

        for (uint i=0; i<ResamplingFlashReader_NUM_BUFFERS; i++ ) {
            if (_buffers[i] != NULL) {
                free(_buffers[i]);
                _buffers[i] = NULL;
            }
        }
    } else {
        __enable_irq();
    }
}

int ResamplingFlashReader::available(void) {
    return _file.available() / _playbackRate;
}

void ResamplingFlashReader::close(void) {
    if (_playing)
        stop();
    _file.close();
}

void ResamplingFlashReader::updateBuffers() {

    bool forward = (_playbackRate >= 0.0);

    while (_readBuffer >= 0
           && isInRange()
           && bufferIsAvailableForRead[_readBuffer]) {

        //Serial.printf("read buffer: %d (_numBuffers:%d) \n",_readBuffer, _numBuffers);
        int16_t *buffer = _buffers[_readBuffer];
        bufferIsAvailableForRead[_readBuffer] = false;

        _last_read_offset = _file_offset;
        uint16_t numberOfBytesToRead = AUDIO_BLOCK_SAMPLES * 2;
        if (!forward) {
            if (_file_offset < 0) {
                // reverse playback, last buffer, only read partial remaining buffer that hasn't already played
                numberOfBytesToRead = _file_offset + AUDIO_BLOCK_SAMPLES * 2;
            }
            _file.seek(_file_offset < 0? 0 : _file_offset);
        }
        //Serial.printf("\nreading %d bytes, starting at:%d (into readbuff %d) - _file_offset:%d\n", numberOfBytesToRead, _file.position(), _readBuffer, _file_offset);
        int numRead = _file.read(buffer, numberOfBytesToRead);
        _bufferLength[_readBuffer] = numRead;
        //Serial.printf("read %d bytes\n", numRead);

        if (_playbackRate < 0) {
            _file_offset -= numRead;
        } else
            _file_offset += numRead;

        if (numRead > 0) {
            _readBuffer ++;
            if (_readBuffer >= ResamplingFlashReader_NUM_BUFFERS)
                _readBuffer = -1;

            _numBuffers++;
        } else {
            _readBuffer = -1;
            //Serial.printf("\n Not able to read anymore buffers for the moment...\n", numRead);
        }
    }
}

bool ResamplingFlashReader::isInRange() {
    if (_playbackRate >= 0.0) {
        return _file_offset < _file_size;
    } else {
        return _file_offset + AUDIO_BLOCK_SAMPLES * 2 > 0;
    }
}