Play an audio stream with a Cortex-M0+

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
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?

Re: Play an audio stream with a Cortex-M0+

Quoted text here. Click to load it
  
Quoted text here. Click to load it
  
Quoted text here. Click to load it
  
Quoted text here. Click to load it
  
Quoted text here. Click to load it
s.

mbed.org has a mp3 player that works on M0+.
Use DMA to fill the audio buffer from SPI.
Maybe You may also use the DMA to feed the DAC.

Bye Jack

Re: Play an audio stream with a Cortex-M0+
Pumping audio from storage to speaker is a matter of keeping the  
pipeline full so the the output pointer is always ahead of the input  
pointer.  You'll need some amount of buffer memory for that.  Start by  
loading your buffer, and when it reaches some comfortable level of  
playable data, start outputting it.  While you're waiting for the output  
mechanism to drain your buffer to some tolerably low level, you can be  
filling the pipe from SPI memory.

DMA varies among MCUs so only you will know about that.  I suspect DMA  
will be the key to your success unless your MCU is extremely fast or  
unloaded, in whcih case you might not need it.  I suggest you use it if  
you have it.

I've had good results using mu-law compression when fidelity  
expectations are low.  You can find mu-law codec code on the web.  You  
might find that compression is not needed.  Large SPI memory devices are  
cheap and PCM wave files aren't that big so storage limitations should  
be ok for you (YMMV, of course).

JJS

Re: Play an audio stream with a Cortex-M0+
On Wed, 03 May 2017 12:22:15 +0200, pozz wrote:

Quoted text here. Click to load it

I know the M3 supports peripheral to peripheral DMA but I'm not sure
about the M0.  It's not that hard to set up the channels once you kind
of get your head around it.  Transfer chaining makes it a lot easier.
SPI read is a little of an issue as you have to keep the DMA controller
issuing SCLKs.  If the M0 will do p to p you should be able to setup
the DMA descriptors, fire and forget until you get the final
transfer complete interrupt.


--  
Chisolm
Republic of Texas


Site Timeline