electro-smith / libDaisy

Hardware Library for the Daisy Audio Platform
https://www.electro-smith.com/daisy
MIT License
312 stars 131 forks source link

Loading .WAV files into RAM #502

Open MarianoDesivo opened 2 years ago

MarianoDesivo commented 2 years ago

I need to store wav files into Daisy’s RAM, and then play those files (from RAM) on command.

Is there an example about that?

If not, how could I program this? Do I have to use the SDRAM location from 0xC0000000 to (0xC0000000 + 64Mb) ?

I haven’t found documentation about it

stephenhensley commented 2 years ago

This would make for a great example program, but it does not currently exist.

You can do this a few ways, but the simplest would require you to know roughly what size your files are going to be.

You can create buffer of 16-bit integers in the SDRAM with:

int16_t DSY_SDRAM_BSS my_sample[EXPECTED_SAMPLE_COUNT];

and then using fatfs, to read through your wave file can load the file:

disclaimer: I'm writing this off the top of my head. So it may need some tweaking,

if (f_open(&file_object, "myfile.wav", FA_READ) == FR_OK) {
  UINT bytes_read = 0;
  f_read(&file_object, my_sample,  EXPECTED_SAMPLE_COUNT * sizeof(my_sample[0]), &bytes_read);
}

Now, this will copy the entire wav file, and not just the data. You can parse the wav file first to determine the type, size, etc. and then copy only the samples themselves to the buffer(s).

Worth mentioning as well, that streaming performance when using 4-bit I/O with an SD card can be very good (though not as good as the SDRAM interface). So if you need to work with more than 64MB of audio files you can work directly off of an SD Card.

Also worth mentioning that the SDRAM is volatile memory, and does not store its state between power cycles. So you will need to load these files in from somewhere every time the module boots (it is possible to similarly load files into the 8MB QSPI, but the process is slightly different).

I'll leave this issue open for now as a discussion, and we'll migrate it into the guide for working with external SDRAM

Hope that helps to answer your question!

MarianoDesivo commented 2 years ago

Hi @stephenhensley thanks for the reply

As I don't know what will be the length of the Wav files, could I use an array for the whole SDRAM length? int16_t DSY_SDRAM_BSS my_sample[1024*1024*32]; Then I will store some variables with the index of the beginning and end of each sample

The whole program would be something like this:

int16_t DSY_SDRAM_BSS my_sample[1024*1024*32];

void AudioCallback(AudioHandle::InterleavingInputBuffer  in,
                   AudioHandle::InterleavingOutputBuffer out,
                   size_t                                size)
{
   for(size_t i = sample.start; i < sample.end; i += 2)
    {
        out[i] = out[i + 1] = s162f(my_sample[i]);
    }
}

int main(void){
   init things

   f_open(WAVSAMPLE);
   sample = parse(WAVSAMPLE);
   for(int i = 0; i< sample.size; ++i){
      my_sample[i] = extractRawData(WAVSAMPLE);
   }

   while(1);
}

Do I have to make a buffer to use in the AudioCallback function? Instead of directly using the SDRAM array