Change Audio Block Size

Status
Not open for further replies.

chipaudette

Well-known member
Is it possible to change the size of the audio blocks?

I see that their size seems to be defined by the AUDIO_BLOCK_SIZE. After some poking around, I see that this variable/macro is defined in the Teensy3 core...

https://github.com/PaulStoffregen/c...560d7a008ccb150b0ec603a/teensy3/AudioStream.h

I see that there are two values defined here...one for 128 (the default for most folks?) and 64. Can I force it to use the 64 instead of the 128? or, is there any way for me to set it to some other value (like 32 or 256)?

I don't need all of the functions in the Audio library to work when I change the block size. My goal is simply to get the samples from the Audio Adapter at my preferred block size and to push samples to the Audio Adapter at my preferred block size. If I break all of the other functions, that's fine. If any of the functions still happen to work, I'd feel lucky.

Can I change the block size? How?

Thanks,

Chip
 
From AudioStream.h:
Code:
#if defined(KINETISK)
#define AUDIO_BLOCK_SAMPLES  128
#define AUDIO_SAMPLE_RATE    44117.64706
#define AUDIO_SAMPLE_RATE_EXACT 44117.64706 // 48 MHz / 1088, or 96 MHz * 2 / 17 / 256
#elif defined(KINETISL)
#define AUDIO_BLOCK_SAMPLES  64
#define AUDIO_SAMPLE_RATE    22058.82353
#define AUDIO_SAMPLE_RATE_EXACT 22058.82353 // 48 MHz / 2176, or 96 MHz * 1 / 17 / 256
#endif

For the audio-shield, you have to edit the file memcpy_audio.S too (see the comments)
 
Several other places in the audio lib also depend on 128 samples per block, but most of the code will adapt if you just edit AudioStream.h.

The block size should always be a multiple of 16 or at least 8, since many places in the audio lib process 2, 4 or 8 samples per loop.
 
The latest version fixes many of these hard-coded dependencies. If anyone finds this old thread, the issues mentioned here are now mostly fixed.
 
I'm finally getting around to trying different block sizes. By changing AUDIO_BLOCK_SAMPLES in AudioStream.h, I can change the block size, as suggested above. The code successfully compiles and, through println() statements, it reports that the block size has changed. But, the audio sounds horrible.

My test sketch (including modified AudioStream.h) is on my GitHub: https://github.com/chipaudette/Open...no/Teensy Time Domain Audio/ChangeBlockLength

Or, for those who prefer a code listing here in the forum...

Code:
//Use my custom version.  Only changes AUDIO_BLOCK_SAMPLES
#include "AudioStream.h"  //comment this out to return to the original version

//These are the includes from the Teensy Audio Library
#include <Audio.h>      //Teensy Audio Library
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// Create audio objects
AudioControlSGTL5000    sgtl5000_1;    //controller for the Teensy Audio Board
AudioInputI2S           i2s_in;        //Digital audio *from* the Teensy Audio Board ADC.  Sends Int16.  Stereo.
AudioOutputI2S          i2s_out;       //Digital audio *to* the Teensy Audio Board DAC.  Expects Int16.  Stereo
AudioSynthWaveformSine   testSignal;          //xy=107,185

const int n_freqs = 3;
int freq_ind = 0;
float freqs_Hz[n_freqs] = {600.0, 700.0, 800.0};

// Make all of the audio connections
AudioConnection         patchCord1(testSignal, 0, i2s_out, 0);
AudioConnection         patchCord2(testSignal, 0, i2s_out, 1);
//AudioConnection         patchCord1(i2s_in, 0, i2s_out, 0);
//AudioConnection         patchCord2(i2s_in, 0, i2s_out, 1);


// define the setup() function, the function that is called once when the device is booting
void setup() {
  Serial.begin(115200);   //open the USB serial link to enable debugging messages
  delay(1000);             //give the computer's USB serial system a moment to catch up.
  Serial.print("ChangeBlockLength: AUDIO_BLOCK_SAMPLES: ");Serial.println(AUDIO_BLOCK_SAMPLES);

  // Audio connections require memory
  AudioMemory(10);      //allocate Int16 audio data blocks
 
  // Enable the audio shield, select input, and enable output
  sgtl5000_1.enable();                   //start the audio board
  sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN);       //choose line-in or mic-in
  sgtl5000_1.volume(0.8);      
 
  //setup sine wave as test signal
  testSignal.amplitude(0.01);
  testSignal.frequency(freqs_Hz[(freq_ind++) % n_freqs]);
  
} //end setup()

// define the loop() function, the function that is repeated over and over for the life of the device
unsigned long lastUpdate_millis = 0;
void loop() {
  if ((millis() - lastUpdate_millis) > 2000) {
    Serial.println("Changing Frequency...");
    testSignal.frequency(freqs_Hz[(freq_ind++) % n_freqs]);
    lastUpdate_millis = millis();
  }
} //end loop()

And here's the first few lines where I modified AudioStream.h...

Code:
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
//#define AUDIO_BLOCK_SAMPLES  128  //original
#define AUDIO_BLOCK_SAMPLES 64   //my trial!
//#define AUDIO_BLOCK_SAMPLES 32   //my trial!
#define AUDIO_SAMPLE_RATE    44117.64706
#define AUDIO_SAMPLE_RATE_EXACT 44117.64706 // 48 MHz / 1088, or 96 MHz * 2 / 17 / 256
#elif defined(__MKL26Z64__)
#define AUDIO_BLOCK_SAMPLES  64
#define AUDIO_SAMPLE_RATE    22058.82353
#define AUDIO_SAMPLE_RATE_EXACT 22058.82353 // 48 MHz / 2176, or 96 MHz * 1 / 17 / 256
#endif

It sounds fine at 128, but horrible at 64. Ideally, I'd like to go down to 32, but it doesn't make any sound at 32 with this test sketch.

Any thoughts as to what I'm doing wrong?

Thanks so much!

Chip
 
Using the I2S input, I get similar behavior: N=128 sounds fine, N=64 sounds super-distorted, and N=32 is silent.
 
So this is interesting. I found that everything seems to work fine if I ensure that audio_block_t is still 128 points long, even if the block size is shorter...

Code:
typedef struct audio_block_struct {
	unsigned char ref_count;
	unsigned char memory_pool_index;
	unsigned char reserved1;
	unsigned char reserved2;
  #if AUDIO_BLOCK_SAMPLES < 128
	int16_t data[128];
  #else
        int16_t data[AUDIO_BLOCK_SAMPLES];
  #endif
} audio_block_t;

This seems to solve the distortion problem at N=64 and the silence problem at N=32. With this modification (based on my limited initial testing), it now sounds fine!

Why should it matter that I keep the length of array up at 128?

Chip
 
Can you please test the opposite: No I2S Input ? Maybe with a simple sine instead.

Thanks for the quick reply....but that's what I did in post #5...I used the AudioSynthWaveformSine instead of I2S_Input. The result was that 128 was fine, 64 was distorted, and 32 was silent. Am I misunderstanding your question?

Again, changing the size of the array in audio_block_t makes this problem go away. Weird! Why?

Chip
 
There still a I2SInput in post #5. But ok, i did not see that it is not connected.
Are you using the latest beta - Teensyduino ?
I'm sure that it worked some weeks ago - it was me who fixed it... but i did not touch the I2SInput - that's the reason for my question re: I2SInput.

Can you pls remove that line ?
I can take a closer look, but not today.

Edit: Please make sure to use the latest beta. Perhaps load the audio-lib and teensy-core from github.

If that still not works, I'll search for the problem.
 
Last edited:
There still a I2SInput in post #5. But ok, i did not see that it is not connected.
Are you using the latest beta - Teensyduino ?
I'm sure that it worked some weeks ago - it was me who fixed it... but i did not touch the I2SInput - that's the reason for my question re: I2SInput.

Can you pls remove that line ?
I can take a closer look, but not today.

Edit: Please make sure to use the latest beta. Perhaps load the audio-lib and teensy-core from github.

If that still not works, I'll search for the problem.

I'm currently running Teensyduino 1.32. I see it's now up to 1.35. So, normally, I would download the installer and run it. But, that's so old-fashioned! Based on your suggestion, I'm going to fork the "cores" and "Audio" repos. I have a question about where to clone them to my local machine...

I'm pretty sure that I know what to do about the Audio library. I think that it can be cloned down into my usual Arduino libraries directory under "My Documents\Arduino\Libraries\". Then, once it is in place, I can delete the old version that the Teensyduino installer had originally put in the Arduino program directory. That's seems pretty easy for me to understand.

But, what do I do with the "cores" repo? Can I just clone it down under the "Program Files (x86)\Arduino\hardware\teensy\avr\cores"? My impression was that the installation process also altered pieces of the Arduino IDE. If I simply clone the "cores" repo, won't I be missing out on something?

This is fun!

Chip
 
Last edited:
In this case, i'd try the beta-installer first - it supports newer Arduino-"IDE"s, too - and it has other improvements.
After that, you can update the core from github. On windows, it is inside [..]\Arduino\hardware\teensy\avr\cores\
 
But, what do I do with the "cores" repo? Can I just clone it down under the "Program Files (x86)\Arduino\hardware\teensy\avr\cores"?

Yes.

My impression was that the installation process also altered pieces of the Arduino IDE. If I simply clone the "cores" repo, won't I be missing out on something?

Yes, you'll be missing all the other libraries, and changes within examples (eg, File > Examples > Teensy), and patches to the IDE java code.

But rarely do the IDE java patches change. If you have an older Arduino, like 1.6.12, the previously installed patches are probably the same. When new things are added, like the improved status display on the serial monitor title bar, they're typically done only in the newest Arduino version. I only back-port patches to old Arduino versions when they're *really* important.

If you want to build the IDE changes from source, here's the code:

https://github.com/PaulStoffregen/Arduino-1.8.1-Teensyduino

The simplest way it to just build with "ant", and then copy the compiled pde.jar and arduino-core.jar into your IDE's lib folder (or within the app bundle if using a Mac). If you want to play with your own edits, the simplest way is to use Linux and delete those jar files from an already-installed copy of Arduino, and create symbolic links to the copied copies in the source tree's "app" folder.

Also, be sure to use the correct version of the Java JDK. For Arduino 1.8.1, that's 8u111 for Windows & Linux, or 8u92 for Macintosh. You can always figure out which version of Java is needed by extracting the manifest files from the compiled JAR files. The version of ant isn't really important, as Arduino's build.xml file doesn't depend on newer features.

The installer also puts the ARM toolchain into hardware/tools/arm, and recently we're experimenting with a new version.

I try really hard to take care of all these thorny details automatically with the installers. But if you *really* want to play with this stuff, you certainly can.
 
In this case, i'd try the beta-installer first - it supports newer Arduino-"IDE"s, too - and it has other improvements.
After that, you can update the core from github. On windows, it is inside [..]\Arduino\hardware\teensy\avr\cores\

I don't know what the "beta-installer" is. I looked at the PRJC teensyduino downloads page and there's only one for Windows. I didn't see any installers on the GitHub repo, but I'm not sure where I'd look.

So, I installed the regular 1.35 installer. I did not replace any of its files from the GitHub repo...it's just a regular 1.35 installation. I did, however, pull down the latest Audio library from Paul's github repo.

With this new setup, I took the new AudioStream.h and added the same lines that I added in post #5 (meaning that this uses the original definition for audio_block_t):

Code:
#define AUDIO_BLOCK_SAMPLES  128  //original
//#define AUDIO_BLOCK_SAMPLES 64   //my trial!
//#define AUDIO_BLOCK_SAMPLES 32   //my trial!

When I run this code, N=128 sounds great, N=64 is distorted, and N=32 is silent. And, for N=32, the Teensy appears to be hung up / frozen. The code in my loop() routine is supposed to generate a serial message every 2 seconds. It's not doing that. So, in this test configuration, it does not appear that the new Teensyduino or new Audio library has helped.


Now, your second suggestion was to comment out my AudioInputI2S, even though it wasn't part of any AudioConnection. That's a fine idea. When I comment out the AudioInputI2S, the behavior does change: N=128 sounds great; N=64 is now silent (and appears to be frozen based on the lack of serial messages); and N=32 makes now tones whereas before it was silent. For N=32, it's not actually working properly, though. There's a sharp pop with every change in frequency and, after a variable amount of time (~10-20 seconds) it switches from clean-sounding to distorted and is then frozen for-real. Also, at N=32, the serial monitor twitches offline/online every 2 seconds in sync with my commands to change the frequency of the tone. So, clearly, the system is not happy. Regardless, commenting out the AudioInputI2S did have an effect, which surprises me, but it wasn't a fully satisfactory effect.


Finally, when I do my trick by changing the length of the data array in audio_block_t, everything seems to work. Bizarre!

Code:
typedef struct audio_block_struct {
	unsigned char ref_count;
	unsigned char memory_pool_index;
	unsigned char reserved1;
	unsigned char reserved2;
  #if AUDIO_BLOCK_SAMPLES < 128
    int16_t data[128];
  #else
    int16_t data[AUDIO_BLOCK_SAMPLES];
  #endif
} audio_block_t;

Chip
 
Last edited:
? That's interesting.
Are you sure, that it is now using the "official" audio-lib and not an older one from your documents-directory ?

Let me try it, but give me some days. Next Weekend. I'm sure that we can fix it (again? hm..)
 
Last edited:
? That's interesting.
Are you sure, that it is now using the "official" audio-lib and not an older one from your documents-directory ?

The only Audio library on my system is now the one in my documents directory and it is my local clone of my fork (https://github.com/chipaudette/Audio) of Paul's repo. I have removed the Audio library that had been in "C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries". So, I believe that it is the right one.

I'm happy to check other places if you suspect that I'm using the wrong one.

Thank you so much for trying to work this through. Again, my sketch is in my repo: https://github.com/chipaudette/Open...no/Teensy Time Domain Audio/ChangeBlockLength

Also, I'm using a Teensy 3.6 at 180MHz, not that I expect that to be relevant.

Chip
 
Last edited:
Hi FrankB!,

I was wondering if you might have had a chance to take a look at this? I know it's not your job or anything, but if it's motivating at all, know that this is still an issue that perplexes me and that I'm still trying to figure out. Any insights that you have (or discover) would be so valuable!

Thanks so much,

Chip
 
Ok, i took my spare 3.6 and a audioshield. Then, I edited the Audiostream.h :
Code:
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
//#define AUDIO_BLOCK_SAMPLES  8
//#define AUDIO_BLOCK_SAMPLES  8
//#define AUDIO_BLOCK_SAMPLES  32
#define AUDIO_BLOCK_SAMPLES  64
//#define AUDIO_BLOCK_SAMPLES  128
#define AUDIO_SAMPLE_RATE    44117.64706
#define AUDIO_SAMPLE_RATE_EXACT 44117.64706 // 48 MHz / 1088, or 96 MHz * 2 / 17 / 256
#elif defined(__MKL26Z64__)
#define AUDIO_BLOCK_SAMPLES  64
#define AUDIO_SAMPLE_RATE    22058.82353
#define AUDIO_SAMPLE_RATE_EXACT 22058.82353 // 48 MHz / 2176, or 96 MHz * 1 / 17 / 256
#endif

and uploaded the "Guitar" example to the Teensy (180MHz, like you. Option "fastest" with and without LTO)
It works absolutely flawlessly with the above blocksizes (but, really, i would'nt use 8 or 16 due to overhead)

Edit: Just for fun, as i have the hardware on my desk, i tried larger blocksizes of 256, 512 - they work too! (maybe useful for some special cases..)

I'd try to remove (take a backup before) your arduino-installation and local libraries and try it again with a fresh install (latest beta)..

If that does not work, please post an example that I can copy&paste ?
 
Last edited:
This probably won't work right with the FFT 1024 audio object as is. With a block size of 64 your only getting half the number of samples before the processing step.
 
Maybe yes, your're right. Do you have time to repair the fft ? :)
There might be other minor problems, too.
Audio-Output works well.
 
If that does not work, please post an example that I can copy&paste ?

Thank you so much for testing this!

In post #16, I offered my code via my GitHub. My code doesn't work, while yours does.

In trying it again on my system (because of your extra effort here in post #21...with the implied message "yes, Chip, it works on my own system...you must be doing something wrong"), I played around a little more. Yes, my code still fails, but now I know why...sorta.

In my GitHub code, you can see that I have a revised AudioStream.h sitting in the same directory as my sketch. That's the one that has the new #define for the new blocksize. To use the modified AudioStream in my sketch, I simply do a #include "AudioStream.h" to include my local AudioStream. In my mind, the crucial detail was that I did this #include before I include Audio.h. Therefore, in my mind, my local AudioStream.h is being used for all of the Teensy Audio Library, while the one in hardware/avr/cores/Teensy3 is being ignored (due to the "#ifndef AudioStream_h" at the top of the file). That's what I thought. Apparently, I was wrong.

When I edit the AudioStream.h that lives in hardware/avr/cores/Teensy3, the system works at different block sizes. When I edit my local version, despite including it prior to including, it does not work.

Why does my way fail?

How can I offer a custom version of AudioStream.h without forcing one to edit the version down deep in a protected space like Program Files (x86)/Arduino?

Thanks so much for your help!

Chip
 
Last edited:
If a person did want to set a custom sample rate and custom block size, I had thought that maybe something like this would work:

In a person's sketch, prior to #include <Audio.h>:

Code:
#define CUSTOM_BLOCK_SIZE_SAMPLES  64

And then, in a revised version of the audio library's AudioStream.h, it might have something like this:

Code:
#ifdef CUSTOM_BLOCK_SIZE_SAMPLES  
  #if (CUSTOM_BLOCK_SIZE_SAMPLES == 64)
    #define BLOCK_SIZE_SAMPLES  64
  #elif (CUSTOM_BLOCK_SIZE_SAMPLES == 32)
    #define BLOCK_SIZE_SAMPLES  32
  #else
    #define BLOCK_SIZE_SAMPLES 128
  #endif
#endif

Might something like this work, if the Audio library's AudioStream.h were suitably modified?

Might something similar work to enable a custom sample rate, as well?

Chip
 
Status
Not open for further replies.
Back
Top