New library for PWM playback from SD cards: SimpleSDAudio

Hi folks, good news from me: 8)
I've updated the library and now you don't need to call worker() anymore if you provide the SSDA_MODE_AUTOWORKER flag at initialization. I've also added a doorbell (with ding-dong-sound) example, the SD card file access example and edited the examples for autoworker-function. Also there is the fancy AbsoluteMinimum-Example to play the example-audio-file from card that contains just this:

/*
 SimpleSDAudio absolute minimum example, plays file EXAMPLE.AFM from root folder of SD card (CS on pin 4)
 through speaker/amplifier at pin 9 for ATmega328 / pin 44 for ATmega1280/2560.
 */
#include <SimpleSDAudio.h>
void setup()
{ 
  // SdPlay.setSDCSPin(10); // Enable if your SD card CS-Pin is not at Pin 4... 
  SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_MONO | SSDA_MODE_AUTOWORKER);
  SdPlay.setFile("EXAMPLE.AFM"); 
  SdPlay.play();
}

void loop(void) {
}

Enjoy!

nice job..

(for those lazy.. here is the link to the lib: SimpleSDAudio – Hackerspace Ffm)

So using what you've posted.. all you need to do in the MAIN loop..

for a button 'check/press' is:

(dummy code:)

if(digitalread(button1) == LOW){
     SdPlay.setFile("EXAMPLE2.AFM"); 
     SdPlay.play();
}else if(digitalread(button2) == LOW){
     SdPlay.setFile("EXAMPLE3.AFM"); 
     SdPlay.play();
}

etc..etc..

no need to init or de-init anything?

the more demos showing all the functions and features make for popular usage!!..

I still have gotten to the 2/4 channel stuff I saw mention.. or how all that works! lol..

(side question and really more a general hardware questions.. is there any other things we can add to the single output on D9 to make it sound a bit better?.. I only have a 100uF cap right now.. no resistors any thing)..

I dont/wont have enough room to have a pot/wiper and a ton of extra components.. but if adding another cap or resistor or two will help improve.. Id like to try!).. I saw some examples use a resistor.. and some use only a cap..etc.

@Tuttut, did you see my post at #84 about use on the 1284P? Thanks.

Thanks once again .. I'll get to work on that. It's amazing how I can spend several hours getting nowhere and then you guys come up with a nice straightforward solution that leaves me wondering why I didn't think of that ! GRRRR. Anyway many thanks for the help, its greatly appreciated.

Hi,
@tack: have you looked inside the new version? I think I've put your stuff in, but it would be nice if you can try if also autoworker works on your platform as it needs additional stuff in those hardware-settings.

@xl97: You still need the init function that does a lot internally like setting up the file-system and configuring the audio ports. For Button example see the doorbell example that is also new in my library.

hello Tuttut

i just finished an analysis of pwm distortion, and then thought it would be cool to make a good and cheap wav player. and it turns out it is cool, and you have already done it. thanks for the work, i always enjoy finding projects like this. if you are open to suggestions, here are some things that my research has shown to make improvements in the audio quality.

  1. use 14b, phase correct pwm, at 62khz clock rate. you never really get the full 16b anyways, even with perfect resistors, due to distortions building up in the noise floor. also, perfect resistors are difficult to come by, even with trimming, due to the variability of the internal resistance of the arduino.

  2. use 3.9k / 499k resistors for the mixing. the output resistance is around 40ohms, so this keeps its error component low in comparison to the 3.9k.

  3. dont bother with the external logic chips, they have a lot of jitter in comparison to the arduino itself, and introduce phase modulation and associated distortions. also, the noise floor on the arduino i tested was -110dB, which was below the pwm noise floor for frequencies above 1kHz. with the usb disconnected, the arduino isnt that bad.

  4. you can try changing the depth / location of pwm to get further gains, but its probably not too significant for audio (as compared to pure tones), as the maximum amplitude is usually low anyways.

here are the writeups if youre interested:

distortion analysis:

dual pwms:

again, great work, im looking forward to trying it out.

I'm loving this, already using it in a solar-powered project.

Now, maybe I'm daydreaming, but I would love to be able to output AM Radio Modulation instead of audio. ]:smiley:

http://dangerousprototypes.com/2011/10/05/am-sofware-radio-using-arduino/

Code:
http://dangerousprototypes.com/forum/download/file.php?id=5107&sid=9ed56f436c83604b287f75ec73f11146

Hi g_u_e_s_t,
a warm welcome on the journey of pushing the audio quality from 1-bit (and 2-bit) outputs to new frontiers! Raising audio quality from such limited systems is a challenging task but I am amazed how far we get. Some years ago I also shared the opinion that without an additional DAC it would be hard to get audio out of an AVR that sound far better than telephone.

I read your writeups about PWM distortion and - at least - tried to understand them. I think you did a very good theoretical work, even I didn't understand everything yet. But I think you did a really great work toward raising audio quality out of such constrained systems and breaking actual known limits. Some time ago I started my journey by coding a high-order delta-sigma-modulator that converts audio-files to pulse-dense-modulated single bit-streams that I played back through the SPI port of the AVR at rates of up to 2 MBit/s. That way I moved most of the quantization noise out of the audible band, but for whatever reason, the quality on real-world hardware was worse than expected and because it is not possible to do mixing easily with pulse-width-modulated data I stopped my efforts. I wanted then to make something that makes good audio quality playback as easy as possible to use and with minimum hardware effort and started SimpleSDAudio.

With your research results I think we should try to get a step further in quality, but it's time to leave theoretic and try it at the real thing. Let's try if and when phase-correct PWM really sound better than fast PWM. Does it make sense for 2-bit systems to go from 16-bit to 14-bit (or even less) for better results? How about pre-filtering the input audio files to something like PWM-Freq/4? We will loose some high-frequency audio-information but maybe reduce perceived noise also.

You measured -110dB noise floor, I can't believe this really. When SimpleSDAudio stopped at a fixed PWM value, there is really no audible noise, but how about when it is accessing SD card and the AVR has to work harder? I thought the noise is much higher than but maybe I am wrong and that noise is really only from those artifacts you described - I have to try again...

Also interesting that Ti-paper about logic outputs. I wondered why it is so hard to drive speakers at reasonable volume, but with a 74AC14 it should be again worth a try to drive a speaker as this thing cost only a quarter Euro.

Keep on your good work! I look forward to see what happens if you apply your thoughts to real hardware...

@WilliamK: Interesting thing that AM modulation. BTW: hook up a laser-pointer or a focused LED to the digital audio output pin and receive it over quite a distance using a small solar-panel from garden-light connected to an amplifier - it works great.

hello Tuttut,

one more thing. you can pre-distort a wav file so that it plays back identical to the source material. the pwm transform is a known function, and although not invertible, it can be compensated for perfectly. i have yet to implement this, but i have read research papers on it, which prove it mathematically.

Tuttut:
Hi,
@tack: have you looked inside the new version? I think I've put your stuff in, but it would be nice if you can try if also autoworker works on your platform as it needs additional stuff in those hardware-settings.

OK, I've now had time to test it and I can report that it works perfectly 'out of the box'. Many thanks for adding those mods to the definitions as it will save re-applying them in future.

I've also tested the Autoworker mode and that also works fine on the 1284P. It has been tested with a 3 minute music file of 27Mb size and it played perfectly in 8 bit stereo full rate, sounding good through a set of hacked active PC speakers.

At the moment this is just running with a 100R in series with each channel. I want to use this now with a little 3W stereo amplifier as an onboard solution. - http://www.technobase.jp/eclib/OTHER/DATASHEET/pam8403.pdf

Any thoughts on input filtering/control prior to the amp? At the moment I'm thinking of a .1uF capacitor in series and a 10k trimmer to control the input level, as per attached schematic. I don't need to be able to adjust volume by the user, just set it and leave it.

The amplifier's datasheet uses an 0.47uF input capacitor, if this is already there you don't need the additional 100nF one in series. The trimmer is ok, you want it otherwise it will be to loud. If audio output is to noisy try adding a capacitor after the trimmer to GND to do a little low-pass filtering. I don't know a value but experiment in range of 100nF to several uF for best results.

I've added the additional cap pads to my design but I can always jumper them out for testing on the prototype boards.

One thing I am doing is setting a 28 pin DIL socket inside my 40 pin one, with some approrpiate 328P pins joined through to 1284pins. This lets me use a 328P on the same board if I don't need all the peripherals or FLASH/SRAM of the 1284P/644P.

On the 1284P the 2 pins used for Channel 1 & 2 (8 Bit Stereo Full Rate) don't clash with anything else. On the 328P Channel 2 is Pin 10, clashing with SPI hardware SS.

I saw the wiring.c patch for the timers, saying that pin 6 & 5 can be used to get 16 bit stereo at half rate. What I would like to do, is use 6 & 5 instead of 9 & 10 for the default 8 bit stereo. Is this possible? I tried making a few changes to the defs file but realised it needs some of the hardware timer definitions altering too if it is possible to make it work.

If possible then It would be ideal if there was a setup parameter to use the alternate pins IF the patch is applied. I'm sure this would be useful for 328 users who want 8 bit stereo but use Ethernet shields or other SPI devices.

First, hardware SS is often only an issue when SPI is used as slave, which is often not the case. Second, to use the pins 6 & 5 on mega328 Arduinos, you have to apply the wiring.c patch as you already figured out and then you have to patch the file SimpleSDAudioDefs.h. Scroll to the end and you find the last big #else part that sets up all the stuff for mega328 Arduino. Below that, there is the same part again but this time for use pin 6 & 5, but it is commented out. Rework the comments that the old #else-part for pins 9 & 10 will become commented out and activate the part below instead. Then audio will use pin 6 & 5, but it requires the wiring.c patch. Beware, I have not tested that thoroughly so please leave a note if it works for you.

Hi,

Does this also work with Arduino with ATMEGA168 only?

Hi, I am sorry, I think the minimum requirement is ATmega368 ATmega328P. The ATmega168 is to low on RAM.7

How about ATMEGA 328.
Sorry. I don't know which is which.

Additional: I tried converting a .wav file but no file appears on the "converted" folder I created.
Is there any requirement for the format of the wav file?
How do I choose the appropriate batch file?
A real newbie in here, hope you understand.

@Tuttut - sorry, I didn't realise that section was there. I'll give that alternativ section a try and report back on whether it works ok. Many thanks again, it's very much appreciated.

meowth08:
How about ATMEGA 328.
Sorry. I don't know which is which.

Additional: I tried converting a .wav file but no file appears on the "converted" folder I created.
Is there any requirement for the format of the wav file?
How do I choose the appropriate batch file?
A real newbie in here, hope you understand.

It works fine in both the 328 and the 328P.

You need to choose the batch file for the playback rate and type you want. I have used 8 bit Mono Fullrate and 8 bit Stereo Fullrate and find the quality very good with a set of PC 2.1 active speakers.

If you are struggling for cycles (a processor intensive sketch) then you may want to try the Halfrate variants.

I've not found any problems with any Wav files at all. I've used downloaded movie/TV sound effects and also used freeware converters to convert a music track MP3 to Wav and then drop on a batch file to convert to 8 bit Stereo Fullrate .asm file, that then played very nicely in SimpleSDAudio

Hi,

What free converter did you use?
What are the settings like encoding etc?
This is killing me for quite a while now :stuck_out_tongue:

I have a .wav file.
attributes: 64000 Hz, 8-bits, mono.
format: PCM uncompressed

On the command prompt, it says:
A subdirectory or file converted already exists.
Press any key to continue . . .

Hi,
maybe you have a Wav-File that contains something that sox is not aware of, try converting it using commandline and verbose mode of sox. Or try a program like Audacity to import and export the file to a proper PCM Wav-file.
Maybe you even look at the wrong path of the converted folder...