`available()` never true teensy 4.1

aocole

New member
Hi folks. First time trying the audio library. I'm using a teensy 4.1 without the shield, with the circuit illustrated here - I have replaced the 10k resistor with 2.2k as instructed. Here's my setup:
teensyaudiosetup.jpg

There's a little parallax in the image, but the green signal wire is connected to pin 16 on the teensy. There is foam tape insulating the bottom of my little audio input daughterboard. The other wiring is for Octows2811 but I'm not using it in this example.

I'm just trying to run any of the simple examples such as PeakMeterMono but I'm finding that the `available()` call on line 36 never returns true. Same for trying fft256 and fft1024 - available() is never true. If I just do a normal arduino analogRead from A2 and plot the result I can see a waveform that makes sense for the audio signal I'm delivering (see below). The DC offset on the signal line is about 1.2V.

Any ideas why `available()` isn't true? I searched the forum but only found an old thread about a clock speed issue that had been resolved by Paul.

Screen Shot 2022-08-23 at 3.38.08 PM.jpg
 
Try this.

Code:
#include <Audio.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=164,95
AudioAnalyzePeak         peak1;          //xy=317,123
AudioConnection          patchCord1(adc1, peak1);
// GUItool: end automatically generated code

AudioInputI2S            unused_but_needed_for_audio_update;

void setup() {
  AudioMemory(40);
  Serial.begin(9600);
}

// for best effect make your terminal/monitor a minimum of 31 chars wide and as high as you can.

elapsedMillis fps;

void loop() {
  if (fps > 24) {
    if (peak1.available()) {
      fps = 0;
      int monoPeak = peak1.read() * 30.0;
      Serial.print("|");
      for (int cnt=0; cnt<monoPeak; cnt++) {
        Serial.print(">");
      }
      Serial.println();
    }
  }
}

Also make sure you have at least Teensyduino 1.57 installed. In Arduino, click Help > About to check. Version 1.57 added major improvements to AudioInputAnalog.
 
Committed code which will automatically start a timer do update the audio library when no hardware input or output has taken responsibility for updates.

https://github.com/PaulStoffregen/cores/commit/503cd9f307d9f1482d92b8e3618d39d4df8a70ed

I really should have done this years ago. I was seriously considering it for 1.57, but concerned about risking this sort of "large" change too close to release. So now that we're at the beginning of the cycle that will become 1.58, seems like a good time to finally get this done.
 
Committed code which will automatically start a timer do update the audio library when no hardware input or output has taken responsibility for updates.

https://github.com/PaulStoffregen/cores/commit/503cd9f307d9f1482d92b8e3618d39d4df8a70ed

I really should have done this years ago. I was seriously considering it for 1.57, but concerned about risking this sort of "large" change too close to release. So now that we're at the beginning of the cycle that will become 1.58, seems like a good time to finally get this done.

Hey Paul, is it also a good time to maybe revisit this pull request to make audio buffers more performance friendly by getting the buffers on cache aligned boundaries?
https://github.com/PaulStoffregen/cores/pull/421
 
Committed code which will automatically start a timer do update the audio library when no hardware input or output has taken responsibility for updates.

https://github.com/PaulStoffregen/cores/commit/503cd9f307d9f1482d92b8e3618d39d4df8a70ed

I really should have done this years ago. I was seriously considering it for 1.57, but concerned about risking this sort of "large" change too close to release. So now that we're at the beginning of the cycle that will become 1.58, seems like a good time to finally get this done.
Hmmm. Possibly you should have done it for most people's use cases, most of the time, but you just broke one of my test techniques:
Code:
#include <Audio.h>

// GUItool: begin automatically generated code
AudioSynthWaveform       waveform1;      //xy=379,207
AudioRecordQueue         queue1;         //xy=568,209
//AudioOutputI2S           i2s1;           //xy=580,283

AudioConnection          patchCord1(waveform1, queue1);
// GUItool: end automatically generated code


void setup() 
{
  while (!Serial)
    ;

  AudioMemory(2);
  //AudioMemoryNoForceUpdate(2);

  waveform1.begin(0.95,220.0,WAVEFORM_SINE);
  queue1.begin();
}

// PLot a graph of the waveform at a human-friendy speed
void loop() 
{
  waveform1.update();
  queue1.update();

  while (queue1.available())
  {
    short* p = queue1.readBuffer();

    for (int i=0;i<128;i++)
      Serial.println(*p++);

    queue1.freeBuffer();
  }
  delay(250);
}
Running the audio engine under sketch control can allow close examination of stuff without needing an oscilloscope. I've put in PR#561 which at least allows the option of having a sketch which uses the audio library but doesn't force updates every 2.9ms.
 
Hey Paul, is it also a good time to maybe revisit this pull request to make audio buffers more performance friendly by getting the buffers on cache aligned boundaries?

No, this really isn't a good time for it.

I'm pretty sure the library has several places with hard-coded assumptions about audio_block_struct which will break. They're probably all my fault.

Whether this helps performance seems questionable. I'm pretty sure the only benefit is allowing use of more memory. If this does have a significant performance improvement, maybe a benchmark program would be useful?


but you just broke one of my test techniques:

I replied on Github.

Quick summary: I believe this test case should be done by creating a class which takes responsibility for update, rather than expanding the public API.
 
Something like this?
Code:
#include <Audio.h>

[COLOR="#0000FF"]//==========================================================================================
// Class to "grab" update responsibility so that audio engine updates can be run
// at a speed convenient for debugging.
class AudioUpdateGrabber : public AudioStream
{
    bool update_responsibility;
  public:
    AudioUpdateGrabber() : AudioStream(0,NULL), update_responsibility(update_setup()) {}
    void do_update_all() {AudioStream::update_all();}
    bool has_responsibility() {return update_responsibility;}
    void update() {} // needed to ensure class isn't abstract
};

AudioUpdateGrabber grbr; // putting this before GUItool code should ensure we get the update
//==========================================================================================[/COLOR]

// GUItool: begin automatically generated code
AudioSynthWaveform       waveform1;      //xy=379,207
AudioRecordQueue         queue1;         //xy=568,209
AudioOutputI2S           i2s1;           //xy=580,283

AudioConnection          patchCord1(waveform1, queue1);
// GUItool: end automatically generated code



void setup() 
{
  while (!Serial)
    ;

  AudioMemory(2);

[COLOR="#0000FF"]  // Double-check we grabbed update responsibility
  while (!grbr.has_responsibility())
  {
    Serial.println("Didn't grab update responsibility!");
    delay(250);
  }[/COLOR]

  waveform1.begin(0.95,220.0,WAVEFORM_SINE);
  queue1.begin();
}

// Plot a graph of the waveform at a human-friendly speed
void loop() 
{
[COLOR="#0000FF"]  grbr.do_update_all();[/COLOR]
  
  while (queue1.available())
  {
    short* p = queue1.readBuffer();

    for (int i=0;i<128;i++)
      Serial.println(*p++);

    queue1.freeBuffer();
  }
  delay(250);
}
Seems to work OK: even though it's a bit more tedious to set up, not many people will need it. However...

...another case you've broken is my Dynamic Audio Objects library, I believe: well, you would have if I were to merge this change in. With DAOlib, there are many use cases where a sketch will start with no AudioStream objects created at all, just the AudioMemory. As implemented, your IntervalTimer updater will therefore be created, but as no visible reference is retained there seems no legitimate way of removing it to replace it with a subsequently created object capable of real update responsibility.
 
Back
Top