I need to reproduce a short audio stream with a Cortex-M0+ MCU (it's SAM D21E from Atmel/Microchip). The audio bitstream will be stored in an external SPI Flash memory (I need to manage many short audio streams, so the internal Flash memory is not sufficient). SAMD21 features DAC, SPI and DMA.
The audio will not be high-fidelity. 8 bits at 8kHz sampling frequency is enough. I didn't make many tests, but I think I can use streams with lower bitrates.
Here the problem isn't the compress ratio, i.e. reducing the memory requirements to store all the streams, but to arrange an effective way to transfer samples from external Flash to DAC.
The simplest method I think is to configure the SPI transfer rate exactly at 8kHz, by calibrating the SPI clock (I think I can do): every
125us=8kHz a new sample is received, an interrupt is raised and the value is moved to the DAC register.The only problem I see for this method is that the MCU must be interrupted every 125us. The MCU will run at 48MHz and should manage a serial RS485 38400bps (260us) too.
One solution to free the MCU is to use the DMA peripheral, but I never used it in the past. Will it be possible to use DMA to automatically move the byte received from SPI to DAC register, without interrupting the normal execution code?
Of course this "direct method" (from external memory to DAC output, without processing) can be done with uncompressed 8-bits samples audio streams. If I need to reduce the memory requirements, I need to use a compress (even simple) algorithm... there are many. Anyway in this case I can't move the samples from SPI to DAC, because I need to uncompress the samples.
Is it possible to use a normal (not DSP) Cortex-M0+ MCU to play a compressed audio stream? If yes, what is the best method to:
- arrange the load of compressed stream from external memory
- uncompress the input stream
- move the uncompressed samples to DAC Here the SPI input transfer rate is not perfectly syncronized with the DAC output transfer rate (fixed at 64kHz). I think I have to manage a FIFO buffer with two thresholds. When the FIFO is full over first threshold, the SPI transfer is stopped. When the FIFO is empty lower than the second threshold, the SPI transfer is started again.
Are there some examples to study?