Periodic digital clicks when reading file from SD card on Daisy Seed

hello folks!

I’m currently trying to set up a simple .WAV sampler with this Micro SD card reader on a prototype board, with a Daisy Seed. I did this in order to minimize the instability that would come along with using jumper wires on a breadboard, although I’m not sure if it actually changes anything… because while I am able to get sound to come through, it seems like the sound itself is stuttering audibly at a frequency of around 7Hz. I have tried messing around with the SDMMC speed and bus width, but I am getting the same outcome, when there is sound at all… at standard speed and below, for example, I’m simply not getting anything.

one thing I noticed while looking around various schematics is that pull-up resistors on the data lines for the SD reader on the Patch are rated at 47K ohm, while those on my small module (which are embedded on the board itself and unmodifiable) are at 10K. I’m not extremely well versed in electrical stuff, so I was wondering if this was maybe why I’ve been getting weird results? or if there is something else at play here that I’m completely missing…


this is what I have (the sample is a drone, so the rhythmic pattern is not within the file itself)

some pictures of my breadboard (I have had to use a single jumper wire for the CMD signal since it would’ve been impossible for me to route it to the Seed otherwise):


code is virtually the same as the seed/WavPlayer example in DaisyExamples.

Hi @netherwaves

This could be a bug with the WavPlayer itself, or with the block sizes being used, and not necessarily something wrong with your hardware.

Something you could do to check to see if it’s the code, or the hardware would be to run the code you have, but have the audio output synthesize a sine wave or something very quiet instead of playing back the sample.

With that going on, the erroneous noise would still be there if it’s hardware, or would be gone if its something to do with the code.

Also, I see the DaisyExamples wavplayer example has the block size set to 4, you might try to increase that to something like 24 or 48, which should give the SD card more time to process new data in case it is bandwidth related.

Hope that helps!

thank you for the cues @shensley ! unfortunately, I have tried everything here and it doesn’t seem to fix the problem… the sine tone plays without any discontinuities, and the clicking occurs at any block size, so I’m suspecting there’s something going on in the WavPlayer itself…! I’ll try to look into it and see what’s up with that… although any help from someone more experienced would be appreciated :wink:

EDIT: I have tried implementing the sampler on channel L and the sine tone on channel R in parallel to see if it would affect either:

float sampler_out, osc_out;

for(size_t i = 0; i < size; i += 2)
{
    sampler_out = s162f(sampler.Stream());
    osc_out = osc.Process();
    
    out[i] = sampler_out * 0.1f;
    out[i + 1] = osc_out;
}

the left channel plays the sample with the clicking noises, while the right channel plays the sine tone unaffected

EDIT 2: if I press my hand on the solder traces in the back of the prototype board, the sample starts stuttering in place

interestingly, if i half down the read buffer size in wavplayer.h L.90, the clicking frequency doubles… hmmmmm

at this point i’m really not sure if it’s something to do with the hardware that has trouble reading correctly the SD memory or that of the code that doesn’t connect the tail ends properly when streaming in the audio callback… looking at the code though, nothing seems wrong, but i might be

HUH OKAY SO i’ve made another test and it seems like the file operations are affecting SOUND ENTIRELY and not just the sampler stream itself… plus the Prepare and Stream combos are only chopping up lower frequencies, a 1000Hz sine tone sounds fine but bring it down to 50Hz and it sounds like a square-ish wave… removing the two sampler calls fixes the issue. so could it be that the SD card is overtaking the sound processor, kindof? i dont really know

here is my current code:

#include <daisy_seed.h>
#include <daisysp.h>

// namespaces
using namespace daisy;
using namespace daisysp;

DaisySeed hw;
SdmmcHandler   sdcard;
FatFSInterface fsi;
WavPlayer      sampler;

Oscillator osc;


void AudioCallback(AudioHandle::InterleavingInputBuffer  in,
                   AudioHandle::InterleavingOutputBuffer out,
                   size_t                                size)
{
    float sampler_out = 0.0f, osc_out = 0.0f;

    for(size_t i = 0; i < size; i += 2)
    {
        sampler_out = s162f(sampler.Stream());
        osc_out = osc.Process();

        out[i] = out[i+1] = (osc_out * 0.5f);
    }
}


int main(void) {
    // initialize hardware
    hw.Configure();
    hw.Init();

    // logger
    hw.StartLog(true);
    hw.SetLed(1);

    System::Delay(1000);

    SdmmcHandler::Config sd_cfg;
    sd_cfg.Defaults();
    sd_cfg.speed = SdmmcHandler::Speed::STANDARD;
    sd_cfg.width = SdmmcHandler::BusWidth::BITS_4;

    uint8_t result;
    
    result = (uint8_t)sdcard.Init(sd_cfg);
    hw.PrintLine("SDMMC HANDLER RESULT: %ld", result);

    result = fsi.Init(FatFSInterface::Config::MEDIA_SD);
    hw.PrintLine("FATFS INTERFACE RESULT: %ld", result);

    result = f_mount(&fsi.GetSDFileSystem(), "/", 0);
    hw.PrintLine("F_MOUNT RESULT: %ld", result);
    if(result != FR_OK) return;

    System::Delay(1000);

    FRESULT samplerres = sampler.Init(fsi.GetSDPath());
    hw.PrintLine("SAMPLER RESULT: %ld", samplerres);

    sampler.SetLooping(true);

    osc.Init(48000);
    osc.SetFreq(50);
    osc.SetAmp(0.1);
    osc.SetWaveform(Oscillator::WAVE_SIN);

    hw.SetAudioBlockSize(48);
    hw.StartAudio(AudioCallback);

    for(;;) {
        FRESULT prepResult = sampler.Prepare();

        hw.SetLed(0);
        if (prepResult != FR_OK) {
            hw.PrintLine("PREPARE NOT OK: %ld", (uint8_t)prepResult);
            hw.StopAudio();
            break;
        }
    }
}

i’ve altered the wavplayer functions a bit to be able to catch the FRESULT values of each operation, but otherwise nothing was changed

@shensley do you have any ideas about this?

@netherwaves thanks for the thorough checking!

Looks like it might be an issue within the WavPlayer itself, as you mentioned.

I suspect when it was originally written, there was a perfect/lucky sync between the WavPlayer’s buffer/read size, and the audio block size that made it so that the issue you’re seeing wasn’t happening, or at least wasn’t noticeable.
This could have been due to the file(s) being tested as well, since read times can depend on the size of the file).

I have definitely set up a few custom sample-player applications that are able to play back clean audio. So I’m fairly certain its just a bug somewhere in how the Prepare function is implemented.

We’ll look into the issue a bit on our end and see about getting it fixed up shortly!
I’ve made an issue on Github to track the problem/solution.

1 Like

for those who are curious: i’ve found a potential fix that i’ve documented in the comments of the GitHub issue. essentially i was able to fix the bug by transferring the buffer array as a global object of the sketch (ie. at the root of main.cpp) and assigning it to the SDRAM with the DSY_SDRAM_BSS attribute