Changing AUDIO_BLOCK_SAMPLES causes problem

Status
Not open for further replies.

CTRL

Member
Hi,

I am trying to use AudioOutputMQS of the audio library, with a smaller value of AUDIO_BLOCK_SAMPLES. I changed 128 to 64 in the line

Code:
#define AUDIO_BLOCK_SAMPLES  128

of AudioStream.h. Then the sound became strange, sort of noisy and vibrating, while the tempo seemed unchanged. 32 gave the same kind of result.

My test code was very simple --- the data was from memory (converted using wav2sketch):

Code:
void setup() {
  AudioPlayMemory mp;
  AudioOutputMQS mqs; 
  AudioConnection cn(mp, 0, mqs, 0);
  AudioMemory(5);
  while(true) {
    mp.play(AudioSampleFlute);
    delay(5000);
  }
}

I guess something in output_mqs.cpp might be relevant. How I can use smaller AUDIO_BLOCK_SAMPLES?
 
to change AUDIO_BLOCK_SAMPLES you have to change it in the cores/Teensy3/AudioStreams.h file and recompile the whole system (changing some entry in Tools of Arduino IDE)
 
to change AUDIO_BLOCK_SAMPLES you have to change it in the cores/Teensy3/AudioStreams.h file and recompile the whole system (changing some entry in Tools of Arduino IDE)

Yes, I had recompiled necessary things.
 
Are you just doing this for grins, or is there something specific you're trying to do by changing the block size? In general... I'd say the only reason to decrease the block size might be to try to decrease the latency of your system...

That being said, it does appear that Paul wanted the block size to be adaptable, and 64 should work according to the comments in the code. I guess there are 2 things that could be going wrong:
- there is a hard-coded dependency to a block size of 128 somewhere
- the interrupts are not firing fast enough to account for the smaller block size
 
Are you just doing this for grins, or is there something specific you're trying to do by changing the block size? In general... I'd say the only reason to decrease the block size might be to try to decrease the latency of your system...

That being said, it does appear that Paul wanted the block size to be adaptable, and 64 should work according to the comments in the code. I guess there are 2 things that could be going wrong:
- there is a hard-coded dependency to a block size of 128 somewhere
- the interrupts are not firing fast enough to account for the smaller block size

I guess the first is more likely. Teensy 4 can handle a lot higher frequency interrupts (eg every 1/44100 sec), just by using IntervalTimer straightforwardly. 64/44100 sec is not difficult at all. Instead, something hard coded in the audio library seems to be related to the problem.

Why am I interested in a smaller value of AUDIO_BLOCK_SAMPLES? I was considering feeding MQS audio data extracted from somewhere else on the fly. The data is not predictable---must be generated depending on some other input. When AUDIO_BLOCK_SAMPLES = 128, the minimal data update period is 128/44100 sec, and I felt this could be too long for the given situation (in reflecting a fast change of input). I agree on that decreasing the value of AUDIO_BLOCK_SAMPLES is unlikely to be useful for usual situations with fixed data (eg playing music from an SD card).

Alternatively, I also wrote code which generates data every 1/44100 sec and directly drives PWM audio output (with PWM frequency > 2^12 * 44100 Hz, to produce >12 bit amplitude resolution at 44100Hz sampling rate). Indeed this worked well. Teensy 4 is very powerful! But I thought using MQS with the fantastic audio library (which uses DMA!) would be nicer. Especially in reducing the processor load :)

In any rate, as mentioned above, I think the audio library was intended to work with other values of AUDIO_BLOCK_SAMPLES. So perhaps fixing this issue of MQS could be meaningful.
 
Why am I interested in a smaller value of AUDIO_BLOCK_SAMPLES? I was considering feeding MQS audio data extracted from somewhere else on the fly.

Well, I'm not quite sure I understand the use case. As far as I know, MQS is output only... no need to get data from it since it'll be available elsewhere.

If you need to capture sound data, you can use AudioRecordQueue object.

If you are trying to create a PWM output, it would be best to do a DMA implementation and extend the existing PWM output to support T4: https://github.com/PaulStoffregen/Audio/blob/master/output_pwm.cpp
 
Why am I interested in a smaller value of AUDIO_BLOCK_SAMPLES? I was considering feeding MQS audio data extracted from somewhere else on the fly. The data is not predictable---must be generated depending on some other input. When AUDIO_BLOCK_SAMPLES = 128, the minimal data update period is 128/44100 sec, and I felt this could be too long for the given situation (in reflecting a fast change of input).

Probably not a good idea to try to sync your external data sampling frequency with output device interrupt frequency. You should instead hook your data sampling to a separate interrupt with required sampling frequency to fill an audio buffer and pass that on to the output device once requested.
 
Well, I'm not quite sure I understand the use case. As far as I know, MQS is output only... no need to get data from it since it'll be available elsewhere.

If you need to capture sound data, you can use AudioRecordQueue object.

If you are trying to create a PWM output, it would be best to do a DMA implementation and extend the existing PWM output to support T4: https://github.com/PaulStoffregen/Audio/blob/master/output_pwm.cpp

I guess what I said above was not clear enough. Teensy is sampling (non-audio) input data from some other gpio pins, and the desired audio output is being generated from that input data: roughly, audio_output = f(input_data), where input_data may change quickly.

Thanks for the idea on extending existing PWM output code. One thing I was wondering: if one compares the MQS of Teensy 4 which uses one pin and the audio library's PWM output which uses 2 pins, which one is of better quality? Of course an I2S dac must beat both easily, I guess, but if one must choose among these two as a cheaper solution ...
 
Last edited:
Probably not a good idea to try to sync your external data sampling frequency with output device interrupt frequency. You should instead hook your data sampling to a separate interrupt with required sampling frequency to fill an audio buffer and pass that on to the output device once requested.

Yes, the input data sampling can be done separately at different frequency. It was about reducing the latency of 128/44100 sec (= the playing time of one audio data block). Perhaps this might be short enough and I might just forget about that ... Among those which led me to consider this, there is the following comment in AudioStream.h :)

Code:
// AUDIO_BLOCK_SAMPLES determines how many samples the audio library processes
// per update.  It may be reduced to achieve lower latency response to events,
// at the expense of higher interrupt and DMA setup overhead.
//
// Less than 32 may not work with some input & output objects.  Multiples of 16
// should be used, since some synthesis objects generate 16 samples per loop.
//
// Some parts of the audio library may have hard-coded dependency on 128 samples.
// Please report these on the forum with reproducible test cases.
 
One thing I was wondering: if one compares the MQS of Teensy 4 which uses one pin and the audio library's PWM output which uses 2 pins, which one is of better quality? Of course an I2S dac must beat both easily, I guess, but if one must choose among these two as a cheaper solution ...

I have to admit I don't know much about MQS. A quick google search didn't reveal much about it, but I would imagine it would be somewhat better than PWM, otherwise it wouldn't make much sense to offer it.

An I2S codec is definitely the way to go, I have been using the WM8731 with both T3.6 and T4 and it's pretty great. If you don't need all the capabilities that a codec offers, then an I2S DAC is great as well and there are tons to pick from.
 
Status
Not open for further replies.
Back
Top