Staying awake while playing a WAV file

Status
Not open for further replies.

snusmumriken

Active member
I'm struggling with the interaction of the Audio and Snooze libraries. Most applications seem to want the processor to perform other tasks while Audio is playing a WAV file. But those other tasks include going to sleep, which of course stops play.

After studying the examples, I thought the ability of Audio to play while doing something else lay in the lines:
Code:
  while (playWav1.isPlaying()) {
    }    // Wait for the file to finish playing.
So I figured that this was a control issue. I tried moving my play routine (including the above lines) into a function, thinking that control would not pass back to the main loop (containing the sleep command) until the function was complete. That didn't work, the processor still went to sleep mid-sentence, as it were. So I assume the multi-tasking ability is somehow built into the Audio library?

All I want to do is to play the file from beginning to end, then go to sleep until woken by an alarm or timer. Is there a way to do this, please?
 
I do not know well the snooze library, but there is for sure a way to keep it awake with a command which you'd insert between
Code:
while (playWav1.isPlaying()) {
and
Code:
}    // Wait for the file to finish playing.
 
Thanks, both, for looking at this.

What kind of command would you insert?

The options I can see are a counter or a timer. I need to play the whole file, and file length is variable depending which file it is. I can implement the timer option by adding in a list of file lengths (durations) but for future flexibility I'd rather the playing/stopping was automatic irrespective of the file provided. The counter would presumably use millis() in a set of loops?
 
Thanks all for those suggestions.

I had thought that an empty
Code:
while(1){}
loop would hold up the code indefinitely - and come to think of it, I've used it like that when de-bugging. But anyway, I've now tried inserting time-wasting commands to occupy the processor. In doing so, I've discovered that
Code:
playWav1.isPlaying()
returns 0, and never 1. Similarly,
Code:
playWav1.positionMillis()
always returns 0.

So it begins to look as though my difficulty in staying awake may have nothing to do with Snooze. The code I've used, only very slightly adapted from the WavFilePlayer example Paul Stoffregen provides, and with no Snooze features, is below. It plays the file for as long as the delay() function in the main loop allows. Without the delay function it doesn't play. I'd be really grateful if anyone can spot where the mistake lies.

Code:
// Simple WAV file player example
//
// Three types of output may be used, by configuring the code below.
//
//   1: Digital I2S - Normally used with the audio shield:
//         http://www.pjrc.com/store/teensy3_audio.html
//
//   2: Digital S/PDIF - Connect pin 22 to a S/PDIF transmitter
//         https://www.oshpark.com/shared_projects/KcDBKHta
//
//   3: Analog DAC - Connect the DAC pin to an amplified speaker
//         http://www.pjrc.com/teensy/gui/?info=AudioOutputAnalog
//
// To configure the output type, first uncomment one of the three
// output objects.  If not using the audio shield, comment out
// the sgtl5000_1 lines in setup(), so it does not wait forever
// trying to configure the SGTL5000 codec chip.
//
// The SD card may connect to different pins, depending on the
// hardware you are using.  Uncomment or configure the SD card
// pins to match your hardware.
//
// Data files to put on your SD card can be downloaded here:
//   http://www.pjrc.com/teensy/td_libs_AudioDataFiles.html
//
// This example code is in the public domain.

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

AudioPlaySdWav           playWav1;
// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
AudioOutputI2S           audioOutput;
//AudioOutputSPDIF       audioOutput;
//AudioOutputAnalog      audioOutput;
AudioConnection          patchCord1(playWav1, 0, audioOutput, 0);
AudioConnection          patchCord2(playWav1, 1, audioOutput, 1);
AudioControlSGTL5000     sgtl5000_1;

// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

// Use these with the Teensy 3.5 & 3.6 SD card
//#define SDCARD_CS_PIN    BUILTIN_SDCARD
//#define SDCARD_MOSI_PIN  11  // not actually used
//#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13

void setup() {
  Serial.begin(9600);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(8);

  // Comment these out if not using the audio adaptor board.
  // This may wait forever if the SDA & SCL pins lack
  // pullup resistors
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);

  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here, but print a message repetitively
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}

void playFile(const char *filename)
{
  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playWav1.play(filename);

  // A brief delay for the library to read WAV info
  delay(5);

  int temp=playWav1.isPlaying();
  Serial.print("playWav1.isPlaying = ");
  Serial.println(temp);
  Serial.print("Playing, now at ");
  Serial.println(playWav1.positionMillis());

  temp=playWav1.isPlaying();
  Serial.print("playWav1.isPlaying = ");
  Serial.println(temp);
  // Simply wait for the file to finish playing.
  while (playWav1.isPlaying() == 1) {
  }

}


void loop() {
  playFile("SDTEST1.WAV");  // filenames are always uppercase 8.3 format
  delay(5000000);
}
 
works for me
I played your sketch successfully with and without the delay(5000000); So i'm not sure why it's not working for you. I tested on T3.5 using 1.8.8/1.47-beta2 with audio shield and using uSD on shield. Sketch prints
Code:
playWav1.isPlaying = 1
Playing, now at 5
playWav1.isPlaying = 1
then prints it again when the WAV file finishes .... SDTEST1.WAV take about 95 seconds to play. (lengthMillis 95128)

what Teensy are you using? version of IDE and of Teensyduino?

maybe your WAV file is corrupted?? SD lib's listfiles shows
Code:
SDTEST1.WAV		16787550
SDTEST2.WAV		16425698
SDTEST3.WAV		13617358
SDTEST4.WAV		17173152
https://www.pjrc.com/teensy/td_libs_AudioDataFiles.html
 
Last edited:
works for me
I played your sketch successfully with and without the delay(5000000); So i'm not sure why it's not working for you. I tested on T3.5 using 1.8.8/1.46-beta2 with audio shield and using uSD on shield. Sketch prints
Code:
playWav1.isPlaying = 1
Playing, now at 5
playWav1.isPlaying = 1
then prints it again when the WAV file finishes .... SDTEST1.WAV take about 95 seconds to play.

what Teensy are you using? version of IDE and of Teensyduino?

maybe your WAV file is corrupted??

Thanks so much for trying this. It's great but puzzling that the same code works for you.

I'm using a Teensy 3.2, Arduino IDE 1.8.9. Not sure which version of Teensyduino - how do I tell? I installed it on 24 April, installer file dated 23/4/2019.

I suppose it is possible that the WAV filed is corrupted, although it plays OK with that long delay, as do other files on the SD card, including my own WAV files.

I noticed that Paul Stoffregen has at least partially re-written the SD library (here), though I'm not clear why. Should I be using that version?
 
Last edited:
I just ran it with no delay() on T3.2 with 1.8.9/1.47-beta2. you can find the Teensyduino version by clicking on Help in the teensyloader window and then click on About.

maybe a solder problem? can you provide a photo of your Teensy and shield?
 
I noticed that Paul Stoffregen has at least partially re-written the SD library (here), though I'm not clear why. Should I be using that version?
That should be the SD lib installed with Teensyduino. make sure you don't have a local copy of an older SD lib or audio lib....
 
I just ran it with no delay() on T3.2 with 1.8.9/1.47-beta2. you can find the Teensyduino version by clicking on Help in the teensyloader window and then click on About.

maybe a solder problem? can you provide a photo of your Teensy and shield?

Many thanks. I'll do both those things, but it will have to be tomorrow (London time) as I've left the Teensy in my bag at work (lunchtime hobbyist!). I do have photos of the Teensy and audio shield together, but I have since mounted the whole assembly on Veroboard with a 5V supply from battery via a voltage regulator , and an amp. As the batteries are physically disconnected when the Teensy is connected via USB, those components are unpowered, so I'm not sure how the output from that code would be affected.
 
There also a chance the uSD card is misbehaving. Do you have another uSD card that you can try?
 
Possibly solved, fingers crossed

I am running the Arduino IDE as a portable installation from a pen drive. There is an SD library in F:\Arduino portable IDE\hardware\teensy\avr\libraries. There is another SD library in F:\Arduino portable IDE\libraries. Is this likely to cause a problem? Doesn't Teensyduino look by default in its own library folder? I do use Arduino Uno and Nano, so I am reluctant to delete/disable the other copy if it might cause other problems with those boards.

In any case, today I tried the code posted above with a freshly formatted SD card, and it played the SDTEST1.WAV file with and without the delay(500000). The only fault was that the Serial output was
Code:
playWav1.isPlaying = 1
Playing, now at 5
playWav1.isPlaying = 1
playWav1.isPlaying = 1
Playing, now at 5
playWav1.isPlaying = 1
playWav1.isPlaying = 1
Playing, now at 5
etc
I moved the Serial.print commands inside the while() loop, and playWav1.positionMillis() then now updated correctly.

So I've then gone back to the first SD card, and deleted everything except the .WAV files. The .WAV files now play without that delay(500000). However, the Serial output still shows that the playWav1 parameters are not updating:
Code:
playWav1.isPlaying = 0
Playing, now at 0
playWav1.isPlaying = 0
playWav1.isPlaying = 0
Playing, now at 0
playWav1.isPlaying = 0
playWav1.isPlaying = 0
Playing, now at 0
playWav1.isPlaying = 0
etc

I've then re-formatted the first SD card, and copied my .WAV files onto it. The code plays these and now the serial output shows the parameters are updating correctly. https://forum.pjrc.com/images/smilies/smile.png

So the problem was either corrupted WAV files or a mis-behaving SD card. I'm left wondering about two things:

1) Those files I deleted from the faulty card. They were .CSV files written to the card by an extended version of the code which also logged the RTC time at which the .WAV files were played. That file-writing code is tried and tested by me over several years of use in the field with Arduino Unos. File names are the correct 8.3 format. The first 8 characters are numeric (actually the date + file number, e.g. 19052301.CSV), but that has not caused any issue previously. Files were opened, written to, and closed again before the command to play the .WAV file. Is it conceivable that problems are caused just by just frequently writing to the same SD card that the audio files are on?

2) In developing the extended code with Snooze functions in it, I have had to reboot the Teensy many times. I guess this could easily have corrupted the .WAV files? I will now prepare several SD cards from scratch and replace them when I run into problems.

Anyway, I think I'm on the road again, at least until I hit the next problem. Many thanks to all for your tips.
 
Apologies for re-opening this thread, but after some stops and starts, I have to conclude that I am basically stuck on the same problem.

I have certain WAV files that play nicely on my device (Teensy 3.2 + audio shield - see earlier posts for details). These include the SDTEST#.WAV example files. I have others that play on my PC, but will not (ever) play on the Teensy even when newly copied onto a freshly formatted microSD card. An example is available here. I'd be really grateful if someone else would try playing this file! It should sound like a rodent squealing. The file plays fine off the SD card through my PC, but not on the Teensy.

In my code, sound files are played after an interval determined by a Snooze alarm function. My code is writing an event log to the SD card, recording (just before) the start and (just after) the end of every 'play' event. The log file is closed immediately after writing to it. This record-to-log function is not in itself a problem: it does not interfere with the "successful" sound files. So I'm certain I can rule that out.

What I have noticed is that the "unsuccessful" files sometimes start to play, but cut out within a couple of seconds. At this point the Arduino IDE tells me that the Teensy board is missing, which suggests that it has gone to sleep. It should not go to sleep until after the WAV file has finished playing and the log file has recorded the end of the play event. With these 'bad' files, the log file records the end of play within milliseconds of starting (whereas with successful files it is several minutes later, as it should be, depending on the length of the recording).

Please can anyone suggest what might be wrong with certain of my WAV files that makes the device think they have ended almost as soon as they have begun? Can it be something to do with sampling rate? And if so, is it possible to adjust this?
 
maybe your non-playing WAV files are not formatted correctly. here are parameters for Paul's WAV files
SDTEST1.WAV: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz

view properties with audacity or your favorite audio tool. you may need to reformat your PC WAV files to match Teensy audio required encoding. audacity can do such conversions
 
maybe your non-playing WAV files are not formatted correctly. here are parameters for Paul's WAV files
SDTEST1.WAV: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz

view properties with audacity or your favorite audio tool. you may need to reformat your PC WAV files to match Teensy audio required encoding. audacity can do such conversions

Yes, that's done the trick. The 'bad' files were on a much higher sampling rate. Not used Audacity before!

Very many thanks for your help.
 
Hi, I need help in my coding for Teensy 3.2 to play wav.file
It's my first time doing this.
Need help ASAP.

Code:
#include <Wire.h>
#include <Audio.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
 
int myID;
String mySound;
 
AudioPlaySdWav playSdWav;
AudioOutputI2S i2s;
AudioConnection patchCord1(playSdWav, 0, i2s, 0);
AudioConnection patchCord2(playSdWav, 1, i2s, 1);
AudioControlSGTL5000 sgtl5000;
 
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
 
// Function prototypes
void receiveEvent(int count);
void requestEvent(void);
 
void setup()
{
  // Audio board
  AudioMemory(8);
  sgtl5000.enable();
  sgtl5000.volume(0.8);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN)))
    Serial.println("Unable to access the SD card");
  delay(100);
 
  //Setup for I2C slave mode, address 0x0C (=12), pins 16/17
 //inset deubg line to check content of b0 b1
  if (B0 == 0 && B1 == 0)
  {
    myID = 0x0B;
    mySound = "PZ_BG_BR.201";
    //playSdWav.play("PZ_BG_BR.201"); change this to string to show file name
    // add a debug line using printf
  }
  else if (B0 == 0 && B1 == 1)
  {
    myID = 0x0C;
    mySound = "PZ_BIKE.203";
    //playSdWav.play("PZ_BIKE.203");
  }
  else if (B0 == 1 && B1 == 0)
  {
    myID = 0x0D;
    mySound = "PZ_BG_WT.202";
    playSdWav.play("PZ_BG_WT.202");
  }
  else
   {
    myID = 0x0E;
    mySound = "PZ_FRG.204";
    playSdWav.play("PZ_FRG.204");
  }

  Wire.begin(myID); // Join I2C bus with the specified address
  /*Wire.begin(0x0C); // Join I2C bus with the specified address
  Wire.begin(0x0D); // Join I2C bus with the specified address
  Wire.begin(0x0E); // Join I2C bus with the specified address*/
  Wire.setSCL(16);
  Wire.setSDA(17);
  // Register I2C events
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
 
  // LED
  pinMode(LED_BUILTIN, OUTPUT); // Initialize as digital pin LED_BUILTIN as an output
 
  
  // Serial
  Serial.begin(9600); // Start serial for debug
}
 
void loop()
{
// Do nothing...
//delay(100);
}
 
// Function that executes whenever data is received from master
void receiveEvent(int howMany)
{
  while(Wire.available())
  {
    char c = Wire.read(); // Receive byte as a character
    Serial.printf("Reading from Master: %c\n", c); // Print the character
 
 if(c == '1')
  {
    // Start = blink once
    digitalWrite(LED_BUILTIN, HIGH); // Turn LED on
    delay(20);
    digitalWrite(LED_BUILTIN, LOW); // Turn LED off
 
   // If not already playing, start playback
  if (playSdWav.isPlaying() == false)
  {
    Serial.printf("Start playing\n");
    //myID;
    //playSdWav.play("PZ_BG_BR.201");
    //insert debug to show name
    playSdWav.play(mySound);
    delay(100); // Wait for library to parse WAV info
  }
 
 /*if (playSdWav.isPlaying() == false)
  {
    Serial.printf("Start playing\n");
    myID2;
    //playSdWav.play("PZ_BIKE.203");
    delay(100); // Wait for library to parse WAV info
  }*/
  }
}
}
 
// Function that executes whenever data is requested from master
void requestEvent(void)
{
  if(playSdWav.isPlaying())
{
  Wire.write("1", 1); // Send a 1-byte message "1" to indicate playback in progress
}
  else
  {
  Wire.write("0", 1); // Send a 1-byte message "0" to indicate no ongoing playback
  }
}
 
Last edited by a moderator:
Added CODE using "#" on toolbar to above post.

Hi, I need help in my coding for Teensy 3.2 to play wav.file
It's my first time doing this.
Need help ASAP.

...

What help is needed - what is happening or not happening as expected?

There are working PLAY samples linked from PJRC.COM under the AUDIO Tutorial - perhaps start with or look at those?
 
Added CODE using "#" on toolbar to above post.



What help is needed - what is happening or not happening as expected?

There are working PLAY samples linked from PJRC.COM under the AUDIO Tutorial - perhaps start with or look at those?


Hi,
I have 4 teensies 3.2(slaves) and 1 nodemcu act as a master, all slaves will play a different sound,
1st & 2nd teensy = looping sound
3rd &4th teensy = using sensor to make the sound appear

Currently, it only reads 0x0C that is B0 == 0 && B1 == 1
Tried to connect to different port for another teensy, and it didn’t appear diff sound but appear the sound for 0x0C

So, I’m not too sure why only 0x0C is read and the rest are not. And not sure whether my board is the problem or there’s some mistakes or missing in my coding.
 
Your code doesn't compile because playSdWav.play does not accept a String argument. You have to convert mySound from String to a C-style string.

What are you using B0 and B1 for? They are constants - B0 is zero and B1 is one. Only one of your tests of those will ever execute - as you've noticed, it is the code which sets "myID = 0x0C".

Pete
P.S. This should be a new thread. It has nothing to do with "Staying awake while playing a WAV file".
 
Your code doesn't compile because playSdWav.play does not accept a String argument. You have to convert mySound from String to a C-style string.

What are you using B0 and B1 for? They are constants - B0 is zero and B1 is one. Only one of your tests of those will ever execute - as you've noticed, it is the code which sets "myID = 0x0C".

Pete


How do i convert the mySound to C-style string? Sorry is my first time.

The B0&B1 actually to indicate the identity for each teensies.

For teensy 1 = 00
Teensy 2 = 01
Teensy 3 = 10
Teensy 4 = 11

So in the serial monitor it will shows which teensy are playing sound

P.S how to create a new thread, is my first time here
 
The values of B0 and B1 are fixed/defined in the teensy core files ...\hardware\teensy\avr\cores\teensy\binary.h and will be the same no matter which Teensy you are using.

mySound.c_str() will return the address of the C-style string. You can use it as:
Code:
  playSdWav.play(mySound.c_str());

Pete
 
Status
Not open for further replies.
Back
Top