New library for PWM playback from SD cards: SimpleSDAudio

Hi

I think I followed exactly the schematic you posted.
There are 3 voltage dividers connected to MOSI, SCK, and CS.

PLUS: The testing for the BAREMINIMUMWITHDEBUG says that CS pin of SD card goes to digital pin 4 of crapduino.

What part did I not follow sir? I really need the audio ASAP. It's for a school project.

Im saying (to me at least).. it looks like you have the CS pin on the SD card connected to two other places on the Atmega

Is that how the other diagrams posted have it? (two places)

I have tried BOTH (with this library)..

using D4 and D10 and the CS pin...

and of course using D9 as the default audio output pin..

this gives you 'basic' audio output.. unless you build in a filter/amp..etc..

(more advanced/better audio output is use D4 as the CS pin.. and use BOTH D9 & D10 for audio output. [along with a few other components])

I misunderstood the hardware set-up.

Is this correct already? (check image)

If you change the code/sketch it 'could' work...

but if you leave the purple (D4).. and remove the SS (D10)..

it should work out of the box..

you also need to use D9 >>> electrolytic cap >>> speaker >>> GND

remove the SS (D10)..

Does it mean that the voltage divider: D10-----4k7----.----10k-----gnd will be removed?

you just use D4 instead of D10.. everything else is the same..

leave D10 not used (for now)

follow these images in this post.. but instead of using D10 anywhere.. use D4

Hi,
Great lib.But, Is there any scope of varying the pitch/speed of the file in the SD card ?
Thanks.

Hi,
it is not foreseen yet to change the pitch yet, at least not in fine amounts. You can select between half or full-rate, but that's all. If you want to change the playback speed in finer amounts, it is not possible with that library yet and you wont get usable result just by changing the timer rate because the timer already runs at relatively high speed allowing only massive pitch changes.

The easiest way to do such things might be to prepare multiple files on the card each with a different pitch and play those. You can do this using an audio editor like Audacity to prepare such files.

If you really want to go the hard way it should be possible to modify the library to support different playback rates - at least two options came in mind for me, changing the playback-interrupt function or the worker-function. The worker-function is written in plain C and should be easier to modify but with rate-changing it would not be longer operating at sector boundaries. In the playback function rate changing only have influence over buffer empty speed but it is harder to understand as it is written in Asm. The algorithm I would prefer is a phase-accumulator that decides if and how many samples are skipped or repeated for every target sample...

Tuttut

Thank you tuttut for the reply.
OK, I take the easy way you have mentioned.
One more question. I need to play a 5sec audio as a seamless loop:indefinitely .Though I am able to accomplish that with the "Bare minimum" you have provided,there occurs an audio glitch at the end-to-beginning of the file played. The file has perfect zero-crossing at the beginning and in the end.Could you please suggest anything to avoid this problem.
(My gadget: Ardiuno Atmega 328+LC studio SDcard breakout board).
Thank you again.

Hi,
there is no standard way, but you can try this patch (untested yet!)

void SdPlayClass::worker(void) {
  if(!_WorkerRunning && _pBuf && _fileinfo.Size) {
    uint16_t buflencpy;
    _WorkerRunning = 1;
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
      buflencpy = _Buflen; 
    }      
    if(_fileinfo.ActBytePos < _fileinfo.Size) {
        // At least space for 1 sector?
        if(buflencpy < _BufsizeMinus512) {
            int16_t ret;
            ret = SD_L1_ReadBlock(_fileinfo.ActSector++, _pBuf + _Bufin);
            if(!ret) {
               uint32_t BytesLeft = _fileinfo.Size - _fileinfo.ActBytePos;
               _Bufin += 512;
               _fileinfo.ActBytePos += 512;
               if(_Bufin >= _Bufsize) _Bufin -= _Bufsize; 
               if(BytesLeft > 512UL) {
                   ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
                   {
                     _Buflen += 512; 
                   }
                } else {
                   ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
                   {
                     _Buflen += BytesLeft; 
                   }
                   while(1) {    
                     ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
                     {
                        buflencpy = _Buflen; 
                     }
                     if(buflencpy == 0) break;
                   }
                   play();                   
                }
            } else {
              stop();
              _lastError = ret;
            }
        }
    } else {
      // Playback done
      if(buflencpy <= 1) {
        stop();
      }
    }
    _WorkerRunning = 0;
  }
}

Replace the worker-function inside the lib (file SimpleSDAudio.cpp) with the one above. To stop playback you need to use stop() then.

Please try it and tell if it works...

Tuttut

Hi,
Sorry, that patch did not work.
Result : Audio file not played.Instead, there were lot of glitches-only glitches.I have noticed that the glitches came out as a stream (loudest at the start and diminished along the time line and died in few seconds).But that was from "Bare minimum" sketch.
When I tried the " Bare minimum with Debug", it gave a continuous tone of 125 hz approx.(No audio file content played).
But, sketch examples with worker (bare minimum with worker,bare minimum with worker with debug),worked normally,of course with the glitch.
Could you please explain what exactly the patch modifies.
Anyway, thank you for trying to help me.

manmachine.

Hi,
sorry, I did the patch using a too old local copy of the library on my smartphone on-the-go and got an too old lib file. Now I edited my former post, please try to apply the patch again on SimpleSDAudio-Lib V1.03 (the current one). This time I tested it a little. Unfortunately actually there is no flag that tells you if the file played at least once...
Please try again and tell me if it is working for you.

BTW: The patch catches the moment when the worker function puts the last sector (or part of it) of the audio file in the playback buffer. In this case, it waits endless (and therefore precise) until the buffer is completely empty (_Buflen == 0). In this moment it triggers the play() function, which starts the playback again. This is how the play() function works - if playback is still playing it restarts playing from start again (done by calling internally the stop() function). The stop() function resets all the pointer and the buffer for the playback.

Tuttut

Hi,

I'm still getting audio glitch.May be,something wrong (sd card format etc)with my setup.Could you please confirm that the test file I am using (please see attachment)works Ok in your set up?

: Thank you for the explanation about the patch.Now I understand little more about the 'worker' function and I try to understand your libs more deep.

manmachine

440_22kh.wav (21.6 KB)

Hi,

I got it finally working.

But not with that FAKEduino.
I made my own board.

Sadly, outputting an audio is just a part of the project. The whole project isn't working yet.

Question: Are there pins affected when using this library? For example, some digital pins won't work...something like that?

Hi
@manmachine: Hm, I thought about my quick solution and it is wrong - the issue is that the buffer is completely empty when issuing play and that play first reads a whole sector of 512 bytes from card before it starts playback again. This should lead to a fast but not gapless start. I think it will need a bigger overwork to get around this. I could think about modifying the lib to read the sectors byte-wise which will make the lib slower but more flexible. Audio processing will then become possible like gapless playback, fine-tuned playback tempo and mixing. But the lib might be then not as simple to use as now.

@meow...: Please provide more info what is working and what not. Error code of lib or just no sound? Or just no sound in bigger software project?

Hi,
@Tuttut:Thank you for your reply.So, its going to be a different approach!Well,Could you post a FLOW CHART of the proposed lib implementation,what might be a possible solution.

manmachine

hey Tuttut-..

I sent you a PM a couple of days ago.. :slight_smile:

just curious if you got it?

thanks

Tuttut, thanks for the great library. I have an alpha release of my ChipKit port, BasicSDAudio, available on GitHub. I am also working on an amplifier board that would work for any PWM audio output.

Check out the release at:

another demo at:

and info on the amplifier/filter at:

I have yet to incorporate the 1.03 improvements.

I'd like to see/learn more about making this Awesome library better sounding with the use of filter/amp?

Small? (all SMD?)

Is there a schematic posted for it?

I am VERY happy Tuttut released this lib.. it was a HUGE missing part of the Arduino community (easy audio)..
but as 'stock' the volume is just 'meh'... so it needs some filters and an amp for sure for more sound hungry projects..

still learning/finding my way through filters and amps..

thanks!

What timers are used in this library for 16MHz, Full rate mono?

I'm hoping there is a timer or two open that I can use to output PWM so I can brighten and fade an LED while the audio file is playing.

In the case that there is a timer I can use, would using the timer affect the audio too much?

Thanks.