Playing two .RAW files at once

Status
Not open for further replies.

insane

Active member
So, from what I've read, it looks like you should be able to play two .RAW files at the same time. However, (from the two files on the SD) the first one loads, but the second doesn't. If I switch the order, then the other file plays--but not second. Am I doing something wrong in my code?

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

// GUItool: begin automatically generated code
AudioPlaySdRaw          playRaw_sdHeartSound_A; // xy = 204.1999969482422,    193.99998474121094
AudioPlaySdRaw          playRaw_sdHeartSound_B; // xy = 204.1999969482422,    280.20001220703125
AudioAnalyzeRMS         rms_A;                  // xy = 452.20001220703125,   183.1999969482422
AudioAnalyzeRMS         rms_B;                  // xy = 454.20001220703125,   310.20001220703125
AudioMixer4             mixer_SD;               // xy = 505.20001220703125,   245.99998474121094
AudioOutputI2S          i2s_speaker;            // xy = 714.2000122070312,    284
AudioAnalyzePeak        peak_QrsMeter;          // xy = 722.2000122070312,    208.99998474121094
AudioConnection         patchCord1( playRaw_sdHeartSound_A,     rms_A           );
AudioConnection         patchCord2( playRaw_sdHeartSound_A, 0,  mixer_SD,     0 );
AudioConnection         patchCord3( playRaw_sdHeartSound_B,     rms_A           );
AudioConnection         patchCord4( playRaw_sdHeartSound_B, 0,  mixer_SD,     1 );
AudioConnection         patchCord5( mixer_SD,                   peak_QrsMeter   );
AudioConnection         patchCord6( mixer_SD,               0,  i2s_speaker,  0 );
AudioConnection         patchCord7( mixer_SD,               0,  i2s_speaker,  1 );
AudioControlSGTL5000    audioShield;              // xy = 155.1999969482422,  354.00001525878906
// GUItool: end automatically generated code

#define       inpA      0
#define       inpB      1

bool          equalizer = false;

float         rmsA      = 0.0f;
float         rmsB      = 0.0f;

uint32_t       cnt      = 0;

elapsedMillis fps;

const char    *fileNameA = "HBMURMUR.RAW";
const char    *fileNameB = "HBNORMAL.RAW";

Sd2Card       card;
SdVolume      volume;
bool          reading   = true;
bool          playing   = false;


void setup()
{
  Serial.begin( 115200 );
  SPI.setMOSI( 7 );                               // Audio shield has MOSI on pin 7
  SPI.setSCK( 14 );                               // Audio shield has SCK on pin 14

  if ( ( !card.init( SPI_FULL_SPEED, 10  ) ) ||   // Fail if SD is not on Audio shield on pin 10,
    !( ( card.type() == SD_CARD_TYPE_SD1 )        // ...or if SD card is not of Type SD-1,
    || ( card.type() == SD_CARD_TYPE_SD2 )        //                            Type SD-2,
    || ( card.type() == SD_CARD_TYPE_SDHC ) ) )   //                         or Type SDHC.
  {
    Serial.println( "SD card is not connected or unusable" );
  }
  else
  {
    AudioMemory( 10 );
    audioShield.enable();
    audioShield.volume( 0.5 );                    // sets headphone level (only); set between 0.5 - 0.8

    if ( SD.begin( 10 ) )
    {
      Serial.println( "SD card is connected" );
      fps = 0;
      playing = true;
      startPlaying( fileNameA, fileNameB );
    }
  }
}


void loop()
{
  continuePlaying( fileNameA, fileNameB );
}


bool startPlaying( const char *fileA, const char *fileB )
{
  bool  returnState = true;

  Serial.print( "\nEXECUTING startPlaying( " ); Serial.print( fileA ); Serial.println( " )" );
  if ( SD.exists( fileA ) )
  {
    playRaw_sdHeartSound_A.play( fileA );
    mixer_SD.gain( inpA, 0.5 );
    Serial.print( "Playing " ); Serial.print( fileA ); Serial.print( " - " ); Serial.println( fps/1000.0 );
  }
  else
  {
    Serial.print( "Failed to play " ); Serial.println( fileA );
    returnState = false;
  }

//  delay( 10 );
//
  Serial.print( "\nEXECUTING startPlaying( " ); Serial.print( fileB ); Serial.println( " )" );
  if ( SD.exists( fileB ) )
  {
    playRaw_sdHeartSound_B.play( fileB );
    mixer_SD.gain( inpB, 0.5 );
    Serial.print( "Playing " ); Serial.print( fileB ); Serial.print( " - " ); Serial.println( fps/1000.0 );
  }
  else
  {
    Serial.print( "Failed to play " ); Serial.println( fileB );
    returnState = false;
  }
  Serial.println();
  return returnState;
}


bool stoppedA = false;
bool stoppedB = false;
void continuePlaying( const char *fileA, const char *fileB )
{
  if ( !playRaw_sdHeartSound_A.isPlaying() )
  {
    if ( !stoppedA )
    {
      playRaw_sdHeartSound_A.stop();
      stoppedA = true;
      Serial.print( fileA ); Serial.print( " ended - " ); Serial.println( fps/1000.0 );
    }
  }
  if ( !playRaw_sdHeartSound_B.isPlaying() )
  {
    if ( !stoppedB )
    {
      playRaw_sdHeartSound_B.stop();
      stoppedB = true;
      Serial.print( fileB ); Serial.print( " ended - " ); Serial.println( fps/1000.0 );
    }
  }
  if ( stoppedA && stoppedB && playing )
  {
    playing = false;
    Serial.print( "*all play stopped* - " ); Serial.println( fps/1000.0 );
  }
}
 
Serial monitor output

Oh... I should post the output:

Code:
SD card is connected

EXECUTING startPlaying( HBMURMUR.RAW )
Playing HBMURMUR.RAW - 0.01

EXECUTING startPlaying( HBNORMAL.RAW )
Failed to play HBNORMAL.RAW

HBNORMAL.RAW ended - 0.01
HBMURMUR.RAW ended - 66.52
*all play stopped* - 66.52
 
Try editing hardware/teensy/avr/libraries/SD/SD_t3.h to turn on the Teensy optimized stuff. Does that make any difference?
 
It may not matter, but should that
Code:
AudioConnection         patchCord3( playRaw_sdHeartSound_B,     rms_A           );
not read rms_B?
 
Wow....yeah, that will definitely be a problem when I add in those associated functions. Thanks. I'll have to change that on Monday so see if it had some effect on the current problem; I'll post back then.
 
following up...

Okay, I did turn on #define USE_TEENSY3_OPTIMIZED_CODE, but the 2nd RAW file still doesn't play. I also corrected the connection in patchCord3--no difference there, either. Turning on the serial output for the RMS instrument shows that there's no input, but offers no epiphany.

Would you mind taking another look, Paul. Here's the updated code that employs the RMS reading...

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

// GUItool: begin automatically generated code
AudioPlaySdRaw          playRaw_sdHeartSound_A; // xy = 204.1999969482422,    193.99998474121094
AudioPlaySdRaw          playRaw_sdHeartSound_B; // xy = 204.1999969482422,    280.20001220703125
AudioAnalyzeRMS         rms_A;                  // xy = 452.20001220703125,   183.1999969482422
AudioAnalyzeRMS         rms_B;                  // xy = 454.20001220703125,   310.20001220703125
AudioMixer4             mixer_SD;               // xy = 505.20001220703125,   245.99998474121094
AudioOutputI2S          i2s_speaker;            // xy = 714.2000122070312,    284
AudioAnalyzePeak        peak_QrsMeter;          // xy = 722.2000122070312,    208.99998474121094
AudioConnection         patchCord1( playRaw_sdHeartSound_A,     rms_A           );
AudioConnection         patchCord2( playRaw_sdHeartSound_A, 0,  mixer_SD,     0 );
AudioConnection         patchCord3( playRaw_sdHeartSound_B,     rms_B           );
AudioConnection         patchCord4( playRaw_sdHeartSound_B, 0,  mixer_SD,     1 );
AudioConnection         patchCord5( mixer_SD,                   peak_QrsMeter   );
AudioConnection         patchCord6( mixer_SD,               0,  i2s_speaker,  0 );
AudioConnection         patchCord7( mixer_SD,               0,  i2s_speaker,  1 );
AudioControlSGTL5000    audioShield;              // xy = 155.1999969482422,  354.00001525878906
// GUItool: end automatically generated code

// const int  myInput   = AUDIO_INPUT_LINEIN;
// const int  myInput   = AUDIO_INPUT_MIC;

#define       inpA      0
#define       inpB      1

bool          equalizer = false;

float         rmsA      = 0.0f;
float         rmsB      = 0.0f;

int32_t       cnt       = 0;

elapsedMillis fps;
elapsedMillis elapsed;

const char   *fileNameA = "HBNORMAL.RAW";
const char   *fileNameB = "HBMURMUR.RAW";

Sd2Card       card;
SdVolume      volume;
char          buffer[512];
float         size;
bool          reading   = true;
bool          playing   = false;


void setup()
{
  Serial.begin( 115200 );
  SPI.setMOSI( 7 );                               // Audio shield has MOSI on pin 7
  SPI.setSCK( 14 );                               // Audio shield has SCK on pin 14

  if ( ( !card.init( SPI_FULL_SPEED, 10  ) ) ||   // Fail if SD is not on Audio shield on pin 10,
    !( ( card.type() == SD_CARD_TYPE_SD1 )        // ...or if SD card is not of Type SD-1,
    || ( card.type() == SD_CARD_TYPE_SD2 )        //                            Type SD-2,
    || ( card.type() == SD_CARD_TYPE_SDHC ) ) )   //                         or Type SDHC.
  {
    Serial.println( "SD card is not connected or unusable" );
  }
  else
  {
    AudioMemory( 60 );
    audioShield.enable();
    audioShield.volume( 0.5 );                    // sets headphone level (only); set between 0.5 - 0.8

    if ( SD.begin( 10 ) )
    {
      Serial.println( "SD card is connected" );
      fps     = 0;
      elapsed = 0;
      playing = true;
      startPlaying( fileNameA, fileNameB );
    }

/*
    Serial.println( fileNameA.available() );
    Serial.println( fileNameB.available() );
    if ( fileNameA.available() && fileNameB.available() )
    {
      do
      {
        byte b = fileNameA.read();
        cnt++;
        if ( cnt % (512 * 2048) == 0 ) Serial.print( "." );
        else reading = false;
      } while( reading ) ;
      Serial.print( "\nnumber of bytes: " ); Serial.println( cnt );
    }
    else Serial.println( "files not found" ); //*/
  }
}


void loop()
{
  if ( continuePlaying( fileNameA, fileNameB ) ) 
    rmsAmplitudePeaks();
}


void rmsAmplitudePeaks()
{
  if( fps > 24 )
  {
//    if ( peak_QrsMeter.available()
//        && rms_A.available()
//        && rms_B.available() )
    if ( rms_A.available() )
    {
      fps = 0;
      uint8_t mixedPeak = peak_QrsMeter.read() * 30.0;
      uint8_t fileA_RMS = rms_A.read() * 30.0;
      uint8_t fileB_RMS = rms_B.read() * 30.0;

      for ( cnt=0; cnt < 30 - mixedPeak; cnt++ )
      {
        Serial.print( " ") ;
      }
      while ( ( cnt++ < 29 ) && ( cnt < 30 - fileA_RMS ) )
      {
        Serial.print( "<" );
      }
      while ( cnt++ < 30 )
      {
        Serial.print( "=" );
      }
      
      Serial.print( "||" );
      
      for( cnt=0; cnt < fileB_RMS; cnt++ )
      {
        Serial.print( "=" );
      }
      for( ; cnt < mixedPeak; cnt++ )
      {
        Serial.print( ">" );
      }
      while( cnt++ < 30 )
      {
        Serial.print( " " );
      }
      Serial.print( AudioProcessorUsage() );
      Serial.print( "/" );
      Serial.print( AudioProcessorUsageMax() );
      Serial.println();
    }
  }
}


bool startPlaying( const char *fileA, const char *fileB )
{
  bool  returnState = true;

  Serial.print( "\nEXECUTING startPlaying( " ); Serial.print( fileA ); Serial.println( " )" );
  if ( SD.exists( fileA ) )
  {
    playRaw_sdHeartSound_A.play( fileA );
    mixer_SD.gain( inpA, 0.5 );
    Serial.print( "Playing " ); Serial.print( fileA ); Serial.print( " - " ); Serial.println( elapsed/1000.0 );
  }
  else
  {
    Serial.print( "Failed to play [" ); Serial.print( fileA ); Serial.println( "]" );
    returnState = false;
  }

  delay( 10 );

  Serial.print( "\nEXECUTING startPlaying( " ); Serial.print( fileB ); Serial.println( " )" );
  if ( SD.exists( fileB ) )
  {
    playRaw_sdHeartSound_B.play( fileB );
    mixer_SD.gain( inpB, 0.5 );
    Serial.print( "Playing " ); Serial.print( fileB ); Serial.print( " - " ); Serial.println( elapsed/1000.0 );
  }
  else
  {
    Serial.print( "Failed to play [" ); Serial.print( fileB ); Serial.println( "]" );
    returnState = false;
  }
  Serial.println();
  return returnState;
}


bool stoppedA = false;
bool stoppedB = false;
bool continuePlaying( const char *fileA, const char *fileB )
{
  bool returnState = false;
  
  if ( !playRaw_sdHeartSound_A.isPlaying() )
  {
    if ( !stoppedA )
    {
      playRaw_sdHeartSound_A.stop();
      stoppedA = true;
      Serial.print( fileA ); Serial.print( " ended - " ); Serial.println( elapsed/1000.0 );
    }
  }
  if ( !playRaw_sdHeartSound_B.isPlaying() )
  {
    if ( !stoppedB )
    {
      playRaw_sdHeartSound_B.stop();
      stoppedB = true;
      Serial.print( fileB ); Serial.print( " ended - " ); Serial.println( elapsed/1000.0 );
    }
  }
  if ( stoppedA && stoppedB && playing )
  {
    playing = false;
    Serial.print( "*all play stopped* - " ); Serial.println( elapsed/1000.0 );
  }
  else returnState = true;
  return returnState;
}

The audio files are also attached.
 

Attachments

  • HBMURMUR.zip
    918 KB · Views: 110
  • HBNORMAL.zip
    720.2 KB · Views: 112
more follow up....

Just to rule it out....I rewrote the routine to use .wav files instead of .raw. Same results.
 
a general observation....

Not sure it's THAT consequential--because the code ultimately has to be corrected in order for it to compile--but I've noticed the following:

If I use two diagnostic RMS blocks in the Audio System Design Tool (and having renamed them), the exported text correctly uses the changed names in the AudioAnalyzeRMS/'rms' object definition (e.g. rms_A; rms_B), but then reverts to the default names in the AudioConnection/patchcord definition (i.e. rms1; rms2) upon export. For example, from my code:

Code:
AudioAnalyzeRMS		rms_B;			 	//xy=633.2000122070312,447.20001220703125
AudioAnalyzeRMS		rms_A;				//xy=635.2000122070312,74.19999694824219
...
AudioConnection		patchCord8(  mixer_A, rms1 );	// <-- needs to be corrected to 'rms_A'
...
AudioConnection		patchCord10( mixer_B, rms2 );	// <-- needs to be corrected to 'rms_B'

I am assuming that simply editing the AudioConnection entries to reflect the same names defined in the respective AudioAnalyzeRMS entries works around the problem. But in any event, I thought you might want to know about it--if you don't, already.
 
Status
Not open for further replies.
Back
Top