Play RAW from Serial Flash

Status
Not open for further replies.
interesting. any chance you can quantify that? i only saw 1ms difference vs SDwav (well, last time i've tried. see my post #2 above)

Not really, although 1ms out of 6ms is 16% faster response right off the bat. I'm afraid I don't have a scope to investigate further.

But pressing multiple buttons together was playing havoc with the PS/2 interface, this seems to have been resolved by taking the SDCard access out of the equation. So it follows that SDcard access may have been imparting some delay on my pad input as well.
 
Not really, although 1ms out of 6ms is 16% faster response right off the bat. I'm afraid I don't have a scope to investigate further.

But pressing multiple buttons together was playing havoc with the PS/2 interface, this seems to have been resolved by taking the SDCard access out of the equation. So it follows that SDcard access may have been imparting some delay on my pad input as well.

i see, well, not so terribly important, i was just curious. and i guess that might make sense that the SD card wouldn't scale as nicely. (in my little thing, i have 1 voice per output channel, so i never have more than 4 samples going on simultaneously, and max. 2 files opening at the same time, so i never looked into multiple samples)
 
I measured the time for the play() function.
It's 8-9 us (0.008 ms) with 120MHz.

After play(), we have to wait for the first audiointerrupt (update()) which is within 0.. 2.9 ms.
The update() collects the data and transfers them to the next object in to the chain.

Then, it must be transfered to the output (i.e. i2s). The data is copied to the ouput-buffer, then DMA transfers it to the device.
So, currently i don't know, how a time > 3 ms is possible and can't explain it.

Obviously, there must be something going on i do not see ?
I did not measure the whole time until the first byte is "visible" at the audioutput, but i trust your measurings.
Is there a delay in the sgtl5000 ?
Can someone measure it with dac or pwm output ? (How did you do it?) I 'm really curious where the ms>3 come from...

But it seems (8 us) that I can not change that.

EDIT: Is it possible that other objects (like mixers) add delay ?
Pensive, are there any other audioobjects involved in your measuring ?
And, could it be that the order of the definition of Audioobjects plays a role? If yes, maybe we can increase the speed with some internal sorting during the initialization.

Paul, if you're reading this, can you give a hint ? I'm willing to invest some time if there is potential to optimize some things!
 
Last edited:
The output object might be buffering 1 packet, adding another 2.9 ms.

If you make any "backwards" audio connections from a later object to an earlier one (as the order they're created in your code), or from right to left (in the GUI), that connection incurs a 2.9 ms delay. Forward connections have no delay.
 
Ok.. now i know why you wrote that "TODO"-Comment in the sourcecode...:)
I think it's possible, we have to sort this linked list somehow.

I'll put it on my private todo-list...
 
I measured the time for the play() function.
It's 8-9 us (0.008 ms) with 120MHz.

oh, sorry for the confusion, Frank. that the function returns very fast was never in question.

as mentioned in my initial post, i've tested against a 'real' (ie fully analogue) drum machine (because i don't have a suitable scope and because i was/am mainly interested in using the teensy sample player alongside other gear. ie as a kind of real world test)

that said, i simply had copied over your sketch in post #1, which, i realize now (ie after reading paul's comment below) is full of superfluous stuff, like 10 audioconnections.

i just tried again throwing all that out (see below *) and now i'm down to a little less than ~3.5 ms (again that's relative to the analogue drum), which is more like what i had expected given the 128 sample buffer, ie as the *total* system latency. i don't think there's much to improve about your library! 3.5ms is very decent, though with more stuff going on that seems to impart some latency.

* here's is the code i tested with, at 120MHz:

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <play_serialflash.h>

AudioPlaySerialFlash    sound0;
AudioOutputI2S          dac;   
/* NB: this is using PCM5102a, so nothing else required, ie no i2c stuff */
AudioConnection c0(sound0, 0, dac, 0);

#define CLK_L 2
#define CLK_R 0

volatile uint8_t LCLK;   
volatile uint8_t RCLK;

void CLK_ISR_L() { LCLK = true; }
void CLK_ISR_R() { RCLK = true; }

void setup() {
  
 pinMode(CLK_L, INPUT_PULLUP);
 pinMode(CLK_R, INPUT_PULLUP);
  
 AudioMemory(10);

 attachInterrupt(CLK_L, CLK_ISR_L, FALLING);
 attachInterrupt(CLK_R, CLK_ISR_R, FALLING);
}

void loop() {
  
  while(1){
	
     if (LCLK) {
        sound0.play(0x0);
        LCLK = false; 
	}
     if (RCLK) {
        sound0.play(0x0);
        RCLK = false;
	}
  }  
}
 
Last edited:
It seems we have got to the bottom of things but I neglected to respond to a query:

My audio connections are all in order, I have 16 playRAW (now playRawfromflash) objects, each ofwhich feed into an envelope, then 2 connections out into 2 groups of 4 mixers (left and right groups), each of which outputs into another mixer to pull them together and then out to the output.

I guess the best way to calculate this is simply to record with a mic near the button.

Then you can count the milliseconds from press to sound. Might give this a go, but I'm always on headphones due to snoozing kids.
 
OK, very very very crude test done.

here's my audio library design at present, replace playRAW with the 16Mb flash player object instead.

I trimmed the sound clip of pressing a button at the point where i saw the bass kick sample begin.

Bearing in mind this delay incorporates mechanical switch delays, PS/2 keyboard interface delays and delays related to the audio library as designed below, I think 6ms Is not too shabby at all.

This an unscientific test! So many variables including human error, apologies.

latency.jpg
audio-library-mk1.jpg

question: if I setup passthrough effects or filters, does each effect/filter in the chain impart a 128 sample delay? If so we need some constructors/destructors. I'm sure you can imagine I'd like to add filters and effects to each output, and also to the global output, but I wouldn't want to affect the performance in PASSTHRU mode.
 
Last edited:
Whow, thats a complex project.. amazing that the little T3 has no problem with this !
6ms are ok for this, i think.

I would imagine that some cycles could be saved when using a 16 - channel mixer, instead of chaining 2.
I looked at the source code very briefly, it does not seem to be too complicated to extend the existing mixer to 16 channels.
Perhaps you might want to try it?

question: if I setup passthrough effects or filters, does each effect/filter in the chain impart a 128 sample delay?
I'm not sure, i dont know exactly how it works - but i don't think so.
 
Last edited:
A 16 channel mixer is on my list already :)

That's only a quarter of the project and missing the mastering stage :)

The effects pass through gathers a full sample and returns it untouched so it will definitely chew up cpu, there will impart some kind of delay, just not sure how much.
 
I'm playing with SPIFIFO.
With 8-bit u-law 44KHz, it's more than twice as fast per update ( 3667 ./. 8300 CPU-Cycles ) .

I am very curious about the speed of the other formats.

I'm missing a way to set SS to HIGH manually. Is this possible ?
It would be great for the last transfer. Currently, i'm sending a dummy-byte :-(
 
Last edited:
I updated the repository @ github.
It uses now SPIFIFO per default ( 1.8 - 2.2x Speed, depends on format and F_CPU)
Please look at play_serialflash.h for some configuration-options

With SPIFIFO, AudioStartusingSpi() is not implemented (TODO), but this should'nt be a problem at the moment.

I will pause this little project now, but please feel free to do "pull-requests" at github for updates, bugfixes or new features (Stereo is still missing)

Regards,
Frank.
 
Last edited:
Awesome work Frank!

Im curious about some things and hope one of you can answer them for me.


1. How do I make my Teensy run at 120Mhz? And should I do that? Wont it make it run hotter and shorten its lifespan?

2. Once I have the flash memory chip soldered to my audio board, how do I get the raw audio samples onto the chip?

3. What is the naming convention used for the raw file names on the chip?


Thanks for the info!
 
fwiw/fyi, SPIFIFO seems to work for me ...

@dsparks:

1. How do I make my Teensy run at 120Mhz? And should I do that? Wont it make it run hotter and shorten its lifespan?

there's a line in boards.txt which you need to uncomment.

2. Once I have the flash memory chip soldered to my audio board, how do I get the raw audio samples onto the chip?

https://github.com/FrankBoesing/Arduino-Teensy-Codec-lib/tree/master/examples/sd2serialflash

3. What is the naming convention used for the raw file names on the chip?

there aren't any names involved, at least for the time being. take a look at the library:

AudioPlaySerialFlash :: play(const unsigned int data)

i haven't used it much in practice, so i don't know how people are dealing with filenames.
 
Thank you Mxxx.

I have a device that will let the user select which samples they want to play. So need some sort of way of keeping track of which section of flashrom is for what sample.
 
Still confused as to how and what the constants are getting their value from?

const unsigned int AudioSampleSnare = 0xF8A00; //82583__kevoy__snare-drum-4.raw
const unsigned int AudioSampleTomtom = 0; //86334__zgump__tom-0104.raw
const unsigned int AudioSampleHihat = 0xD0B00; //102790__mhc__acoustic-open-hihat2.raw
const unsigned int AudioSampleKick = 0xDCD00; //171104__dwsd__kick-gettinglaid.raw
const unsigned int AudioSampleGong = 0x9500; //86773__juskiddink__gong.raw
const unsigned int AudioSampleCashregister = 0xE2100; //201159__kiddpark__cash-register.raw

I assume the value after the "=" is the address in flashrom?

How do I know what is what if no names are being associated with it?

Thanks in advance!
 
I dont care how they are stored. I just need to know which ones are what so I can apply my code to finding them based on user selection.
 
Status
Not open for further replies.
Back
Top