Jump to content

SD card polyphonic sample player


Lee

Recommended Posts

Here some pictures of my newly build SD Card sample player module. It's the smallest module in my modular, but so powerfull! Till now I only used one bank full with hardcore-basskicks,kicking through some analoge filters, really lovely! I made a reset button on the module cause when you change MicroSDCards it needs a reset.

I don't need the pushbuttons on this kind of module, midi in works great. But I wanted to make an other module for using in a live-theatre show where I have to trigger some (only2 )sounds. Now we use two CD players for that, and it would be great to swap those CD players with this tiny sample player. But the audiofiles are 5 minutes each and I noticed this SDCard sample player only playes a couple of seconds/sample, or can I change that somewere?

Link to comment
Share on other sites

Hi Roel,

 

You made a really cool module!

 

But I wanted to make an other module for using in a live-theatre show where I have to trigger some (only2 )sounds. Now we use two CD players for that, and it would be great to swap those CD players with this tiny sample player. But the audiofiles are 5 minutes each and I noticed this SDCard sample player only playes a couple of seconds/sample, or can I change that somewere?

 

It can be changed in the code. The current code was made for max 64 samples, each sample index occupies a certain amount in memory, regardless of the actually loaded sample number. Theoretically if You only use max. 2 samples, the longest possible sample length can be at least 32 times longer. There are other possibility to save memory in that case, so I think it can be even longer. I'll make some tests, and try the longest possible sample length with only two samples.

 

Currently I'm working on a new version, that can read wav files too.

Format: pcm, mono or stereo, 16bit, 44.1 kHz sample rate, so called "canonical wav" files.

The wav format allows to read the channel number from the header, and the player works with both the mono and stereo wav files! (Last but not least it's more easier to make such files than raw ones.)

By analysing the header

- if it's a wav file in correct format, plays as a wav format. 
- if it's a wav file but incorrect format, doesn't play it.

- if it's not a wav file, plays as 1 channel raw file (like the original version).

 

Norbert

Link to comment
Share on other sites

If you want a cheap and easy way to control this over midi, check out the ACX Quantizer which also takes the cv input and sends it to a midi-out:

 

http://acxsynth.com/quantizer/quantizerfr.htm

Thanx for the tip, I saw the site before but it's great, with pcb-layouts and and hexfiles for PIC's! really cool, gonna check this out further.

 

Hi Roel,

You made a really cool module!

 

Currently I'm working on a new version, that can read wav files too.

 

Thank you, you made a nice one too. Great news that it'll read wave files!

Edited by Elektruck
Link to comment
Share on other sites

Hi,

 

there is a new version on my playground.

- WAV file support

     Format: pcm, mono or stereo, 16bit, 44.1 kHz sample rate, so called "canonical wav" files.

     For other details see my earlier post.

- Sustain pedal support

 
Have fun!
Link to comment
Share on other sites

  • 1 month later...

Hey,

 

I finally finished my MB Mellotron. It is basically two MB sd card samplers which you can mix. I loaded them up with Mellotron samples. It consists of the following modules:

 

2x STM32F4 running the sampler app

1x STM32F4 running MB NG. Connected to that are… 

      —> keyboard (via DIO matrix)

      —> two encoders with buttons (via DINX1)

      —> 2x16 LCD

      —> sustain pedal input

      —> Midi out

1x self etched PCB with the analog mixer section, headphone amp and a spring reverb emulation

1x PSU with +5V and +12V

 

 

It’s all working pretty well. With 2GB sd cards I get 7-8 voices per card, if you use smaller cards (e.g. 512 mb) you would get more voices (up to 12). The whole sampler is super basic, there is no looping, no envelopes etc, but for a mellotron emulation it is all I need. 

 

Thank you Lee and Norbim for developing this app. Norbims latest version even has some internal effects (chorus, phaser, tremolo) !!!

 

Cheers

Lars

 

 

Edited by rvlt
Link to comment
Share on other sites

What's the explanation for this behaviour? I would have only expected polyphony to be limited by card speed. Does it have to do with the filesystem?

 

It’s all working pretty well. With 2GB sd cards I get 7-8 voices per card, if you use smaller cards (e.g. 512 mb) you would get more voices (up to 12).
Link to comment
Share on other sites

What's the explanation for this behaviour? I would have only expected polyphony to be limited by card speed. Does it have to do with the filesystem?

I am afraid I can't give you a proper explanation for this, but yes, it has something to do with the cluster size and the way the app reads data from the card. Norbim explained it to me in more detail, maybe he could chime in here...

 

I made a test with two cards: a new Sandisk 4GB Class 6 and a very old Sandisk 512MB (no class written on it, I guess 2), and I was able to get 12 voices out the old one but only 7-8 with the new 4GB. When I put these cards in a computer the 4GB one is much faster (like it "should be"..).

Link to comment
Share on other sites

  • 5 weeks later...

Hi Guys - I am VERY impressed with your work on this project so far. Wow!

 

I was wondering if you know how it would be possible to reduce the latency. One of the great things about hardware samplers is that they can achieve much lower latency compared to software.

 

I have a few ideas of how this could be done:

1. First obviously we'd have to reduce the I2S DMA buffer size

2. Second, we could implement a solution where the first X number of samples are preloaded into memory.. so that they can be played instantly while midibox asynchronously fetches the next chunk from the SD card, etc.

 

#2 above is very similar to the DFD concept as used in the popular software sampler as per this page:

http://www.native-instruments.com/en/support/knowledge-base/show/58/what-is-dfd/

 

I believe it could even allow us to use larger samplers and achieve higher polyphony!

 

I wish I knew how to implement this myself, but I am afraid it is beyond my expertise. My dream would be to have as low as 1 ms of latency... as a keyboard player this would be amazing.

 

Anybody know how to do this?

Link to comment
Share on other sites

  • 1 year later...

Hello sample player friends!

First of all, sorry for not replying to the thread for several years (I have literally been rebuilding a house, and not finished yet - so very little time for my fun projects!)

I am really pleased and honoured that there's been some great contributions to the original project, well done everyone! Norbim1 - you've done a great job of adding some of the things that I would have liked to have done. I've not had time to look at the code yet, but i'm interested about the wav support as I was always concerned that with reading the RIFF header (which is far less than one 512 block) that this would then misalign the following reads of a DMA buffer length, meaning that eg for a mono sample you end up reading a block and a bit (2 reads) unless you were able to keep some of the read data in memory to make up for the read on the next block?

At one stage I also had a semi-working pitch bend on the project - it worked ok for pitch bend down, but upwards didn't work! :-)

I'm totally loving the mellotron project!!

Nice work guys

Lee

Link to comment
Share on other sites

Hi Lee, nice to hear You are on board again. Regarding your question my wav code simply replace the RIFF header in the first block with zeros:

                if(samplefile_pos[voice_samples[voice]]==0 && samplefile_type[voice_samples[voice]] > RAW_FILE) // WAV file format, do not play the header
                {
                    for(i=0; i<sizeof(WAVE_FormatTypeDef); i++) {   // Fill the sample buffer header with silence
                        samplebyte_buf[voice][i]=0; // Muted output
                        }
                    //DEBUG_MSG("header mute %d",samplefile_type[voice_samples[voice]]);
                }

It causes some delay, but the RIFF header is only 44 bytes long ( canonical wav). The header equals 22 mono or 11 stereo samples which is roughly a half or a quarter of a ms delay, I think it is acceptable.

Link to comment
Share on other sites

Hi,

Yes it makes sense to just blank out the header. It was more I was thinking of block alignment, ie

RAW -> Very simple, each time around the DMA fill we simply read a 512 byte block (1 read cycle from SD card) for each voice and mix. Every DMA cycle is definitely always block aligned

WAV -> 44 byte offset. First read will pull in the 44 byte header, plus remaining (512-44)= 468 bytes of audio data. Each time around the DMA fill cycle - what happens then? Does the request to read 512 bytes of audio (or whatever the WAV definition dictates) do we read 468 bytes on one read, and the remaining 44 bytes from a 2nd read?

I'm not sure of the answer - I don't think the filesystem libraries cache anything (if they did, then there would be no 'performance hit' due to the block misalignment)?

Anyway - if it works well in practice then it's good enough for me, this was just an area where I didn't implement WAV due to the concern over the 'double read'...

 

Cheers

Lee

Link to comment
Share on other sites

  • 1 month later...

Thank you! Yeah, no milling machine were abused during this project ) Only oldsKool drill&file method, some DIY brackets and countersunk head screws.

Basically this is norbim1 http://svnmios.midibox.org/listing.php?repname=svn.mios32&path=%2Fplayground%2Fnorbim1%2FSD+card+sample+player%2F branch with minor changes in Read_Switch, APP_MIDI_NotifyPackage, Read_Config routines, and 2 global vars added. Toggle switches ON-OFF-ON style: Bank Select - connects PE2 or PC15 to GND, Part Select - connects PC13 or PC14 to GND.

//globals

u8 avlg_hw=0; // set to enable scanning of AVLG bank&part switches on J10

u8 bank_part_offset=0; //bank part offset for Arturia Beatstep Pro

...

 

u8 Read_Switch(void) // Lee's temp hardware: Set up inputs for bank switch as input with pullups, and find if any lines pulled low to select bank

{

 u16 bank_val;

 

 if (lee_hw) {

    bank_val=(u16)MIOS32_BOARD_J10_Get(); // Read all pins, if all pins high, val=0 meaning bank 1, otherwise one pin should be pulled low eg bank_index 0 = bank_val=1 so bank 2

    if(bank_val==0xFF7F) { return 9; } // D7 = 128 low

if(bank_val==0xFFBF) { return 8; } // D6 = 64 low

if(bank_val==0xFFDF) { return 7; } // D5 = 32 low

if(bank_val==0xFFEF) { return 6; } // D4 = 16 low

if(bank_val==0xFFF7) { return 5; } // D3 = 8 low

if(bank_val==0xFFFB) { return 4; } // D2 = 4 low

if(bank_val==0xFFFD) { return 3; } // D1 = 2 low

if(bank_val==0xFFFE) { return 2; } // D0 = 1 low

if(bank_val==0x7FFF) { return 1; } // D15 = 128*256 low

    return 0;      // default to bank 0 (bank val FFFF)

 }

 

 if (avlg_hw) {

   bank_val=(u16)MIOS32_BOARD_J10_Get();

 

   if(bank_val==0xF6FF) { bank_part_offset=0;  return 0; } //Bank1 Part1 0xF6FF

   if(bank_val==0xF7FF) { bank_part_offset=16; return 0; } //Bank1 Part2 0xF7FF

   if(bank_val==0xF5FF) { bank_part_offset=32; return 0; } //Bank1 Part3 0xF5FF

   if(bank_val==0xFEFF) { bank_part_offset=0;  return 1; } //Bank2 Part1 0xFEFF

   if(bank_val==0xFFFF) { bank_part_offset=16; return 1; } //Bank2 Part2 0xFFFF

   if(bank_val==0xFDFF) { bank_part_offset=32; return 1; } //Bank2 Part3 0xFDFF

   if(bank_val==0xFAFF) { bank_part_offset=0;  return 2; } //Bank3 Part1 0xFAFF

   if(bank_val==0xFBFF) { bank_part_offset=16; return 2; } //Bank3 Part2 0xFBFF

   if(bank_val==0xF9FF) { bank_part_offset=32; return 2; } //Bank3 Part3 0xF9FF

   // default:

   bank_part_offset=0;

   return 0;

 }

 return sample_bank_no; // no change

}

 

void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)

{

// replace two occurences of this code:

if((midi_package.note)==sample_to_midinote[samp_no])

// with

if((midi_package.note+bank_part_offset)==sample_to_midinote[samp_no])

...

}

 

void Read_Config()

{

  if(!strcmp(param_name,"lee_hw")) { lee_hw=(int)strtol((char *)(param_value),NULL,10); } // Set lee_hw param

  if(!strcmp(param_name,"avlg_hw")) { avlg_hw=(int)strtol((char *)(param_value),NULL,10); lee_hw=0;} // Set avlg_hw param AND reset lee_hw

...

}

 

 

Tell me if you need complete code or precompiled project.hex

Edited by AVLG
  • Like 1
Link to comment
Share on other sites

Hi AVLG,

Cool module indeed!

2 all:

Last month I made 2 samplebanks for my sample player, 2 octaves of accordion notes, 2 octaves of ContraBass nootes and 5 octaves of piano notes.

The accordion notes sounded quite well but the piano distorted a lot when playing polyphony notes. So I  tried again and normalized the piano sounds with -6dB, but they still distort really fast compared to the accordion sounds, while the accordion sounds are a lot louder.

The only thing I can think of is that the piano sounds are far more clean and harsh sounds compared to the accordion, wich are a lot fuzzier, so you hear the distortion much better with piano sounds. 

For now I play polyphony piano sounds with low level velocity and it works acceptable, but maybe you have some hints to get more volume out of the piano sounds without distortion.

 

And because it was quite some work to set up these sound banks I thought it would be a nice idea to share the files here so you can try them yourselves. Maybe you want to share your sounds also with us. I would love to try those melotron sounds or drumkits.

Here are mine!

Link to comment
Share on other sites

Here's a link to my mellotron sample set (zip file, ~200Mb). Let it be said for the record that I downloaded the samples from somewhere on the internet, and my input was just changing them to the right format (the one required by Lee's original firmware), and making the bank.x files.

Contents (names from the original files, i.e. not my invention)

  • Bank1: MK II Flute
  • Bank2: Cello
  • Bank3: MK II violins
  • Bank4: Combined choir
  • Bank5: Woodwind 2
  • Bank6: M300A
  • Bank7: MK II Brass
  • Bank 8: String section

Bank1 includes also entries for MBSID drum samples (included in the zip), though they're there just because I set them up, thought they could be improved, but didn't get around to it. The samples are assigned to the lowest keys in the range, with the exception of 0x00 (the first address), because it seems to result in unwanted notes for some reason.

[UPDATE: MY DROPBOX ACCOUNT IS NO MORE, SO THE LINK DOESN'T WORK]

https://www.dropbox.com/s/6ccbwf84us5lrdk/SP-mellotron.zip?dl=0

Edited by jjonas
link info update
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...