WaveplayerEx

Frank B

Senior Member
I'm thinking about rewriting the waveplayer, or creating an extended one.
It should support 1-6(8?) channels.

There was a thread where this was requested - I can't find it anymore. grrr.. (it must be some months old? hints?)

I'm searching for wavefiles with this format (uncompressed, of course)- i don't want to create my own because I want to see format variations.
 
I've also considered rewriting the wav file player. Here's some thoughts....

Larger buffer memory is the main thing needed to support playing multiple files simultaneously from modern SD cards. I would like to see the addMemoryForRead(buffer, size) function added to the public API, basically the same as we have for HardwareSerial. This does mean the code is a little more complex to deal with using the added buffer and original buffer, but it's not too difficult or a lot of overhead for a nice API which lets people choose how much extra buffer memory.

Another important piece is coordination between all wav player instances to schedule their use of the SD card. Ideally, on each update (128 audio samples) only 1 instance would attempt to read from the SD card. Maybe a list of all the instances could be managed in a way where the 1 instance most in need of data would do a large read. Then we only suffer read latency once and get all the data with a fast many-sector read. If all instances have large enough buffers, this could allow many to play simultaneously.

Sadly, we don't have an API (as far as I know) to ask SdFat to pre-read data. I believe the library is still only caching 1 or 2 sectors.

I've also thought a few times about adding a useFilesystem(FS &filesystem) function, each instance could be told to access something other than just the SD card.
 
Yes, I had these thoughts as well.
For the codecs I used a lower prioritized interrupt, which reads and decodes the large mp3 frames and if needed - it needs longer than 3ms for one frame - is simply interrupted by the audio interrupt. By then, however, it has already provided enough data for the next audio block and sleeps at some point when it is done - until audio data is needed again. Both work asynchronously and independently of each other.

I have something similar in mind. Then reading can be done independently of the 3ms(default) grid of the audio library and is therefore much more flexible. It just needs another software interrupt.

I have not written anything yet. I'm just thinking about it... :)

But now I enjoy the weather (after the hefty rain) and will sit on my scooter for an hour.


Translated with www.DeepL.com/Translator (free version)
 
If you do write a new one, please consider musically useful API features like play direction (forward, reverse), auto-looping or one-shot playback, playback start point, playback endpoint, and synchronized start/stop. This could put the Teensy on par with something like the Tsunami wav trigger, an $80 device itself.
 
Let me cite a text from here: http://www.piclist.com/techref/io/serial/midi/wave.html
A Bastardized Standard

The WAVE format is sort of a bastardized standard that was concocted by too many "cooks" who didn't properly coordinate the addition of "ingredients" to the "soup". Unlike with the AIFF standard which was mostly designed by a small, coordinated group, the WAVE format has had all manner of much-too-independent, uncoordinated aberrations inflicted upon it. The net result is that there are far too many chunks that may be found in a WAVE file -- many of them duplicating the same information found in other chunks (but in an unnecessarily different way) simply because there have been too many programmers who took too many liberties with unilaterally adding their own additions to the WAVE format without properly coming to a concensus of what everyone else needed (and therefore it encouraged an "every man for himself" attitude toward adding things to this "standard"). One example is the Instrument chunk versus the Sampler chunk. Another example is the Note versus Label chunks in an Associated Data List. I don't even want to get into the totally irresponsible proliferation of compressed formats. (ie, It seems like everyone and his pet Dachshound has come up with some compressed version of storing wave data -- like we need 100 different ways to do that). Furthermore, there are lots of inconsistencies, for example how 8-bit data is unsigned, but 16-bit data is signed. I suggest that you concentrate upon these and refuse to support the work of programmers who feel the need to deviate from a standard with inconsistent, proprietary, self-serving, unnecessary extensions. Please do your part to rein in half-assed programming.

It's unlikely that I will do more than the fmt and data chunk, at first. More channels: yes, sync start& stop: maybe yes.
 
Still looking for wave files... mono, and more than 2 channels.
Nobody?

Is there a need to support 8 Bit?

I have a first version running - for the normal stereo it is working. In theory it supports any # of channels (until it gets too slow). As said, untested.
Everything I can't test will stay untested/unsupported.
 
OK, the 7.1 file, converted to 16 Bits works perfectly :)
So, 8 channels are possible.

2021-07-24 20_41_34-Audio System Design Tool for Teensy Audio Library.png

Of course a setup like above does not make much sense.. you can mix this better "offline" and save as stereo. But you get the idea..

Havn't implemented the intervleaved reads.. this still needs a bit of work.
 
Ok, I need a tool whcih can load and export these files.
Audacity supports export as 2 channel only.

Just catching up on this thread Frank - Found this for audacity: https://shkspr.mobi/blog/2015/07/exporting-multitrack-surround-files-in-audacity/, not sure if this is what you are looking for?

Was about to ask you what the hook up was on the T4 then saw this all the way on the bottom of the PT8211 page:
Code:
Signal     Teensy 3.x   Teensy 4.x   PT8211 Pin
------     ----------   ----------   ----------
 BCK            9           21           1
 DIN           22            7           3
 WS            23           20           2
 +3.3V       3.3V         3.3V           5
 GND          GND          GND           4
 
HI,

thank you! Didn't know that this is possible, because there is no mention in the export dialog. It just says that everything will be converted to stereo... so, thank you for the useful link :)
But SoX works good, too. It's a little more effort.. (commandline tool)

Code:
sox  Nums_5dot1_24_48000.wav -b 16 -r 44100 Nums_5dot1_16_44100.wav
 
@MJS: Does it work wit littleFS?

You are welcome - Sox looks interesting - never knew about it before - nice to have options.

Would think it would work since its all just file based - only thing would be transfer speed for the file not to hiccup - was planning on trying it later but don't think I have a PT8211 board soldered up otherwise would have done it already :)
 
You can use any board! It just needs I2S then, and the control.

Yeah got that one covered after mind got cleared but when compiling for T41 I am getting this error:
Code:
undefined reference to `_AudioPlaySdWavInstances

And before you ask I copied the new .h/cpp files over to the audio library for 1.8.15, TD1.54 - am i missing something else I am suppose to do.

EDIT: this is what I have for setup:
Code:
// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=323,171
AudioMixer4              mixer1;         //xy=647,123
AudioMixer4              mixer3;         //xy=648,212
//AudioOutputPT8211        pt8211_1;       //xy=828,169
AudioOutputI2S           audioOutput;
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer3, 0);
AudioConnection          patchCord3(playSdWav1, 2, mixer1, 1);
AudioConnection          patchCord4(playSdWav1, 3, mixer3, 1);
AudioConnection          patchCord5(playSdWav1, 4, mixer1, 2);
AudioConnection          patchCord6(playSdWav1, 5, mixer3, 2);
AudioConnection          patchCord7(playSdWav1, 6, mixer1, 3);
AudioConnection          patchCord8(playSdWav1, 7, mixer3, 3);
AudioConnection          patchCord9(mixer1, 0, audioOutput, 0);
AudioConnection          patchCord10(mixer3, 0, audioOutput, 1);
AudioControlSGTL5000     sgtl5000_1;  //Just added but still get the error
 
Not sure.. do you use my example sketch?
If yes. Is the line
Code:
extern uint32_t _AudioPlaySdWavInstances;
still there? It's just for debug.. or you can remove the print (it's useless at the moment, anyway)

SGTL:

Yes, two additional lines in setup() are needed:
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);

I've added play(File file) a few minutes ago. Perhaps update from Github.. :) The file must be opened.
 
Hi Frank

My fault - just added those 2 lines on volume just before I read your post.

Ran into one problem - was getting the error :
Code:
   file.open();

So I commented out file.open and it worked :)
 
I've added play(File file);
Is this sufficient for other file systems?

Guess its sufficient. Attached is a sketch that access a 16MB QSPI flash on a T4.1 - I just commented out the lines not being used for this experiment. I also used MTP_T4 to put the file on the flash :)

Just remember to delete the file.open:
Code:
bool AudioPlaySdWav::play(File file, const bool paused)
{
  stop();

  bool irq = false;
  if (NVIC_IS_ENABLED(IRQ_SOFTWARE)) {
    NVIC_DISABLE_IRQ(IRQ_SOFTWARE);
    irq = true;
  }

  startUsingSPI();
  
  //file.open();
 

Attachments

  • WavFilePlayer-210725a.zip
    2.2 KB · Views: 98
Back
Top