New library for PWM playback from SD cards: SimpleSDAudio

Hehe, I now got stereo at fullrate working - I've rewritten the audio output interrupt routine completely in ASM. Next step is heading to 4-channel audio output at 8-bit or stereo-16-bit-output...

That's impressive, congratulations! Thanks for this! 8)

I think this is VERY awesome!!..

thanks!..

I had a (now defunct) PIC project that played audio through PWM output as well.. was very easy/low components too.. missed it!

Now we have this!!!

I read about thew buzz/hiss on the output a little bit.. what was the verdict?

dirty power lines? or something with the SPI bus/lines?

can you easily change the speaker out pin used on the Arduino?

I tried to change this:

uint8_t const SSDA_PWM1_PIN = 9; // OC1A PB1

to

uint8_t const SSDA_PWM1_PIN = 5;

but didnt seem to work on getting output on PWM pin 5

thanks

Hi,
no, you can not change the speaker output because it need very special PWM pins. It it would be that easy I'd already implemented it in the library. May I ask why you need the output pins to be changed?

I figured.. I was hoping another PWM pin could be substituted. :slight_smile:

I was just trying to test it out on a specific (custom) board I had... to see if this lent even more flexibility to it..

I have one more (custom) board I want to try this with..

my 'goal' on my board/project was to have a very small footprint/sized board (which I need for the things I like to do..and full sized dev boards dont cut it).... that had several on-board things that we buy/use shields for.. (SD card.. .wav playback.etc..etc..)

but still be generic enough to apply to many different projects.

(here it is: http://dmstudios.net/misc/scab_assembly/flash_board.jpg)
using the WaveHC library.. it plays .wav files off the SD card..
can also just be used as a data logger or to access stuff on the SD card is audio playback is NOT the focus for the board..etc

here it compared to an Arduino & WaveShield.. (which this was based off...sorta merged together)



I had a failed version of this project I wanted ot test your lib with.. (but no D9 available on that)

the one above.. (current project) does have it (D9) available, so will be testing on that as well..

I've been playing with this library today and have to say it's awesome for what I need, being able to play simple sound effects from game props.

I've just been using a single pin today for 8 Bit Full Rate Mono, but the quality seems really good for what we need. Unfortunately I was using an Ethernet shield for the SD cardso couldn't use D10 to try 16 Bit. That's the only downside I can see, the pin conflict with Ethernet and some LCD Shields (pin 10 is used for backlight brightness control).

Just thought I'd say a big thanks for the time put into this. It's a great piece of work to show what can be done direct from the MCU, without additional hardware.

I connected up to a set of PC amplified speakers and it sounds great with both voice, item and vehicle sounds.

Tuttut:
Hehe, I now got stereo at fullrate working - I've rewritten the audio output interrupt routine completely in ASM. Next step is heading to 4-channel audio output at 8-bit or stereo-16-bit-output...

Hi there,

just stumbled upon your library, it's great!
Many thanks!!

The last version on your website (v1.01) seems to date previous to this rewrite.
Any chance of posting this new version?
I would like to do 16-bit mono @8mhz, so I could use the extra resources...

Thanks again for sharing this!!

Regards Dennis

Hello,

This looks like a great library. Any chance that it could be ported over to include support for the chipkit Uno32? How difficult do you think it would be to do so? It appears that PWM would be relatively simple to port over, but I am not sure about the SD card interface. Any ideas?

With the 80MHz 32bit processor on chipkit, you could have faster SD card read times and high sample rates that would enable more processor free time and better sound. The chipkit is also natively 3.3V, so no level shifters are necessary.

-Thomas

Well, I am starting to port the code over to the chipkit Uno32. First I had to port the library back to Arduino 0023, since that is what the chipkit software--MPIDE--is based on. This was mostly just changing

#include <Arduino.h>

to

#if ARDUINO < 100
#include <WProgram.h>
#else
#include <Arduino.h>
#endif

as well as converting the examples from .ino back to .pde files. After this massaging, I got it to compile in 0023.

The code is not pretty at the moment since I am using a lot of "#if defined (PIC32MX)" to switch between AVR and PIC specific code. I have the SD card library working on the Uno32, so now I need to port over the PWM.

I am running the SD card at 400kHz during initialization and then at 20MHz for everything after that. It is looking like the PWM will be sampled at 78125Hz for full rate and 39062.5Hz for half rate. These values were chosen to give perfect 8bit resolution on the PWM and still be close to the original 62500 and 31250Hz values.

cant wait to see some examples (video) of how it sounds....

For anyone interested in further details regarding my chipkit port, follow the progress at chipKIT32/chipKIT-core ยท Discussions ยท GitHub.

-Thomas

Might I make a request?...

that SdPlay.deInit(); would release whatever SPI timers etc that were grabbed by calling init().

I'm trying to use this in the same project with the Servo.h library, but there's apparently a conflict.
Once I call SdPlay.init(), I can no longer position servos where I want, even if I'm not playing a sound.

Not really a problem since I don't need to do both simultaneously.
I could init(), setFile, play etc., then deInit before returning, but deInit isn't putting things back the way they were...

Any suggestions?
-- thanks

Hi,
I released a new version of the library. The core audio output function is now written in assembler and thus allowing playback of either STEREO and FULLRATE or HALFRATE with four channels. Two channels can be combined to get 16-bit resolution using only a resistor and a trimmer. But in this case the faint noise of the controller can be heard, so I recommend using cheap Schmitt-Trigger buffers (like 74HC14 or else) to get rid of the noise that is on top of the digital signals of the Arduino. With HALFRATE and QUADRO mode and those Schmitt-Trigger circuit you can get a quality that is very good also for music or sound with big dynamics. I is still not full CD quality but quite near to it.

Also I did a patch that you can apply to Arduino that frees the timer0 from all the core functions and makes it available for audio output (timer2 is then used instead of timer0 for core functions like millis and so on). This way audio can be output on pins 6 and 5 instead of pins 9 and 10 on ATmega328 based platforms like Uno, Duemillanove and Ethernet or on all 4 pins together allowing also the Uno to do 16-bit stereo output... :grin:

Further, for Windows user I included the SOX binaries in the library so you can convert WAV-files using the drag'n'drop targets.

Have fun!

Hi Tuttut,

Great work, many thanks for this!!!

As for audio filtering, I've tested with a "Passive, first order low-pass RC filter", which seems to clean out most of the noise with just a resistor and a capacitor, see Low-pass filter - Wikipedia.
I found a 1kohm resistor and a 2.2qf capacitor work out for me, but to be honest, I used a trial and error approach...
Not sure if this even comes in the neighborhood of your buffer approach, but I found the improvement more than adequate for my project.

Once again, many thanks!!!

Regards Dennis

@cobra18t: I like your attempt of porting my library. I included your header-file-stuff for earlier Arduino versions but I never tried the lib on older Arduino IDEs. For SD access you can use my reduced SD library - you have to adapt the sd_l0-files, but the other layers should work quickly on any architecture after that.

@PWBarret: The servo-library (re)initializes the servos after detaching and re-attaching all servos. So try this order: 1. SimpleSDAudio: init -> Play... -> deInit, then Servo: Attach -> control -> detach, then continue with SimpleSDAudio. Both libraries can not work the same time because they share the same timers.

@gateway: You are right, a RC filter might often be an easy way to improve the sound quality on PWM outputs. It works better the higher the PWM frequency is -> SimpleSDAudio uses the highest possible frequency and therefore a RC filter should work pretty well.

Tuttut.

@Tuttut: I saw my changes in the newest version, I will have to try it out in 0023. Thank you for abstracting the SD card library so that I only had to change the "0" level. That made it much easier.

I have a video of a basic 8-bit 78.125kHz stereo sample running on my ChipKit Uno32 using a minimal setup. Check it out:

-Thomas

Thanks for the suggestion...
Maybe it's the servo library that's not properly honoring the detach method then...
If I never attach the servos at all, the sound is good.
But if in my PlaySD function, if I detach both servos upon entry, then init, play, deinit, the sound is garbled.

Hi Tuttut-

I havent kept up with things since you first posted the initial library.. (I see its come very far).. great job!.. and a HUGE benefit to the community IMHO! (thanks)

I am going to re-read the posts.. and go to your site and download the latest..etc..

1.) Does the Arduino board/version matter to use this library? Can the board be a 3.3v @8Mhz board and still be able to utilize this lib?

2.) how much space/resources do we have to 'do' other things WHILE playing audio back?

3.) I saw mention of it being able to be used with IDE v23? IS this added/supported now? or must I use the 1.x+ IDE's?

I have a project in mind that I intend to use this lib for... but the board/pcb is a 'VERY' minimal Arduino circuit running at 3.3v and internal clock @ 8Mhz and SD socket...

(actually.. Im trying to run it off a coin cell.. think thre will be enough voltage (3.0v I believe most coin cells).. if there is enough current for the SD card?

I remember there needs to be a cap in-line with the speaker out line... so I'll probably look at adding that 'on-board' to the pcb itself.....so end result is just solder speaker wires to pcb pads. (or reading up on the low pass filter to put on board)

off to look over the public methods available to us.. and check for any examples on how to utilize each one.

thanks!!

Hi xl97,

  1. The lib is tested on Arduinos using mega328 or mega2560 Arduino based plattforms. I don't know if it will work on things like Leonardo or those USB-supporting-AVR-Devices.
    If you want to use a 8 MHz Arduino you need to convert the samples using the batch-files for 8 MHz, this will half the sampling rate but is often still good enough. If you use a 3.3V Arduino you can attach the SD card without those resistor-divider-stuff directly to the Arduino.

  2. Audio-Lib takes about 1.3KB of RAM, which is a lot especially on mega328 devices. The timer that belongs to the audio-output-pin is fully utilized by the lib and therefore not available anymore. The processor time amount needed is also very high, I guess at nearly 80-90% for highest quality audio stereo. But often that is enough for applications that does not need much power.

  3. I've added some stuff to allow for work in versions prior 1.x, but I never tested that. I think I have heard other people got it to work with v23.

The cap is by the way only to block DC currents from the speaker. It does not act as a low-pass so far as the PWM frequency is out of the hearing range for 16 MHz Arduinos. For 8 MHz you should use the highest rate, then it should be ok as well.

tuttut