Change volume of sample while its playing

Status
Not open for further replies.

mubase

Member
Hi everyone. I'm having fun with some ultrasonic sensors (HC-SR04) and want to use them to change the volume of a sample being played through the audio board in real time. So when a person walks up to the ultrasonic it gets louser and vice versa... Can anyone help me with how I would do this using the audio library objects?
Thanks,
Steve.S
 
In the audio tool add a mixer between the sound source and outputs. In the mixer object, there is the method that allows you to control 1-4 inputs, passing a floating point value, giving the volume. Here is the documentation:

Summary
Combine up to 4 audio signals together, each with adjustable gain. All channels support signal attenuation or amplification.

Audio Connections
  • Port Purpose
  • In 0 Input signal #1
  • In 1 Input signal #2
  • In 2 Input signal #3
  • In 3 Input signal #4
  • Out 0 Sum of all inputs

Functions
gain(channel, level);
Adjust the amplification or attenuation. "channel" must be 0 to 3. "level" may be any floating point number from 0 to 32767. 1.0 passes the signal through directly. Level of 0 shuts the channel off completely. Between 0 to 1.0 attenuates the signal, and above 1.0 amplifies it. All 4 channels have separate settings.

Here is my simple code for playing raw files on the prop shield, using a potentiometer to control the volume (the important part are the two lines that do the analogRead and call mixer1.gain):

Code:
// Converted from the WavFilePlay from the Teensy release:
// hardware/teensy/avr/libraries/Audio/examples/WavFilePlayer/WavFilePlayer.ino
//
// Simple RAW file player example for the prop shield to use the Analog DAC
// and prop shield amplifier to play mono sounds.
//         http://www.pjrc.com/teensy/gui/?info=AudioOutputAnalog
//
// On the prop shield, pin 6 selects the serial flash memory controller,
// and pin 5 enables the amplifier.
//
// This example code is in the public domain.

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

// GUItool: begin automatically generated code
AudioPlaySerialflashRaw  playFlashRaw1;  //xy=149,388
AudioMixer4              mixer1;         //xy=445,386
AudioOutputAnalog        dac1;           //xy=591,379
AudioConnection          patchCord1(playFlashRaw1, 0, mixer1, 0);
AudioConnection          patchCord2(mixer1, dac1);
// GUItool: end automatically generated code

#define PROP_AMP_ENABLE		5
#define FLASH_CHIP_SELECT	6
#define VOLUME_POT		A1

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

  // wait up to 3 seconds for the Serial device to become available
  long unsigned debug_start = millis ();
  while (!Serial && ((millis () - debug_start) <= 3000))
    ;

  Serial.println ("Start prop shield RAW player");

  // Enable the amplifier on the prop shield
  pinMode(PROP_AMP_ENABLE, OUTPUT);
  digitalWrite(PROP_AMP_ENABLE, HIGH);

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

  // Set initial volume
  // mixer1.gain(0, 0.5f);

  // uncomment these lines if you have a potentiometer or trimpot
  // on the pin A1 to control the volume, and comment out the
  // above line
  float vol = analogRead(VOLUME_POT);
  mixer1.gain(0, vol / 1024.0f);

  // Start SerialFlash
  if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
    while (1)
      {
	Serial.println ("Cannot access SPI Flash chip");
	delay (1000);
      }
  }
}

void playFile(const char *filename)
{
  Serial.print("Playing file: ");
  Serial.println(filename);

  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playFlashRaw1.play(filename);

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

  // Simply wait for the file to finish playing.
  while (playFlashRaw1.isPlaying()) {
    // uncomment these lines if you have a potentiometer or trimpot
    // on the pin A1 to control the volume
    float vol = analogRead(VOLUME_POT);
    mixer1.gain(0, vol / 1024.0f);
  }
}


void loop() {
  playFile("SDTEST1.RAW");  // filenames are always uppercase 8.3 format
  delay(500);
  playFile("SDTEST2.RAW");
  delay(500);
  playFile("SDTEST3.RAW");
  delay(500);
  playFile("SDTEST4.RAW");
  delay(1500);
}
 
Thanks Michael this is great. I see you are using the flash memory chip. Can I do the same using the internal memory functions? As in AudioPlayMemory ?
 
Thanks Michael this is great. I see you are using the flash memory chip. Can I do the same using the internal memory functions? As in AudioPlayMemory ?

Sure, I believe mixer is just takes 1-4 inputs of any sort and produces one output. And you can cascade them (feed 4 mixers into another mixer that handle 16 input streams).
 
This code will alter the volume of a sound played from the SPI Flash chip while it is still playing:

Code:
#include <Audio.h>
#include <SerialFlash.h>

AudioPlaySerialflashRaw   sound;

AudioMixer4               mix;
AudioOutputI2S            headphones;

AudioConnection patchCord1( sound, 0, mix, 0 );

AudioConnection patchCord2( mix, 0, headphones, 0 );
AudioConnection patchCord3( mix, 0, headphones, 1 );

AudioControlSGTL5000     sgtl5000;


void loop()
  {
  }

  
void setup() 
  {
  AudioMemory( 32 );

  SPI.setMOSI( 7 );   // MOSI_PIN for audio board
  SPI.setSCK( 14 );   // SCK_PIN for audio board

  if ( !SerialFlash.begin() )
    Serial.println( "Unable to access SPI Flash chip" );

  sgtl5000.enable();
  sgtl5000.volume( .1 );

  sound.play( "A0_16.RAW" );

  delay( 1000 );
  sgtl5000.volume( .2 );
  
  delay( 1000 );
  sgtl5000.volume( .3 );
  
  delay( 1000 );
  sgtl5000.volume( .4 );
  }
 
audio sounding bad

Hi guys and thanks for the input. OK, I've got some code here. It uses the Newping library as I'm using an HC-Sr04 ultrasonic. The sensor works fine but the audio sounds really jumpy. Do I need to use interrupts for the measuerment? What am I doing wrong?

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>
#include <NewPing.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 audio adaptor board
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

#define TRIGGER_PIN  3  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     4  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 400 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

float vol;

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)
{
  Serial.print("Playing file: ");
  Serial.println(filename);

  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playWav1.play(filename);

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

  // Simply wait for the file to finish playing.
  while (playWav1.isPlaying()) {
    // uncomment these lines if you audio shield
    // has the optional volume pot soldered
    //float vol = analogRead(15);
    //vol = vol / 1024;
     unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
      vol=(uS / US_ROUNDTRIP_CM) *0.005;
    //  Serial.println(vol);  check range  --not above 1.00
     sgtl5000_1.volume(vol);
  }
}


void loop() {
 
 
  playFile("night.WAV");  // filenames are always uppercase 8.3 format

  
}
 
Hi Paul. Ive not looked into interrupts as I've got some better results using ping_median to average out the sensor data. Looks like the noise was caused by the data jumping.. Seems a lot smoother now. :)
 
In the audio tool add a mixer between the sound source and outputs. In the mixer object, there is the method that allows you to control 1-4 inputs, passing a floating point value, giving the volume. Here is the documentation:

Summary
Combine up to 4 audio signals together, each with adjustable gain. All channels support signal attenuation or amplification.

Audio Connections
  • Port Purpose
  • In 0 Input signal #1
  • In 1 Input signal #2
  • In 2 Input signal #3
  • In 3 Input signal #4
  • Out 0 Sum of all inputs

Functions
gain(channel, level);
Adjust the amplification or attenuation. "channel" must be 0 to 3. "level" may be any floating point number from 0 to 32767. 1.0 passes the signal through directly. Level of 0 shuts the channel off completely. Between 0 to 1.0 attenuates the signal, and above 1.0 amplifies it. All 4 channels have separate settings.

Here is my simple code for playing raw files on the prop shield, using a potentiometer to control the volume (the important part are the two lines that do the analogRead and call mixer1.gain):

Code:
// Converted from the WavFilePlay from the Teensy release:
// hardware/teensy/avr/libraries/Audio/examples/WavFilePlayer/WavFilePlayer.ino
//
// Simple RAW file player example for the prop shield to use the Analog DAC
// and prop shield amplifier to play mono sounds.
//         http://www.pjrc.com/teensy/gui/?info=AudioOutputAnalog
//
// On the prop shield, pin 6 selects the serial flash memory controller,
// and pin 5 enables the amplifier.
//
// This example code is in the public domain.

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

// GUItool: begin automatically generated code
AudioPlaySerialflashRaw  playFlashRaw1;  //xy=149,388
AudioMixer4              mixer1;         //xy=445,386
AudioOutputAnalog        dac1;           //xy=591,379
AudioConnection          patchCord1(playFlashRaw1, 0, mixer1, 0);
AudioConnection          patchCord2(mixer1, dac1);
// GUItool: end automatically generated code

#define PROP_AMP_ENABLE		5
#define FLASH_CHIP_SELECT	6
#define VOLUME_POT		A1

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

  // wait up to 3 seconds for the Serial device to become available
  long unsigned debug_start = millis ();
  while (!Serial && ((millis () - debug_start) <= 3000))
    ;

  Serial.println ("Start prop shield RAW player");

  // Enable the amplifier on the prop shield
  pinMode(PROP_AMP_ENABLE, OUTPUT);
  digitalWrite(PROP_AMP_ENABLE, HIGH);

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

  // Set initial volume
  // mixer1.gain(0, 0.5f);

  // uncomment these lines if you have a potentiometer or trimpot
  // on the pin A1 to control the volume, and comment out the
  // above line
  float vol = analogRead(VOLUME_POT);
  mixer1.gain(0, vol / 1024.0f);

  // Start SerialFlash
  if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
    while (1)
      {
	Serial.println ("Cannot access SPI Flash chip");
	delay (1000);
      }
  }
}

void playFile(const char *filename)
{
  Serial.print("Playing file: ");
  Serial.println(filename);

  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playFlashRaw1.play(filename);

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

  // Simply wait for the file to finish playing.
  while (playFlashRaw1.isPlaying()) {
    // uncomment these lines if you have a potentiometer or trimpot
    // on the pin A1 to control the volume
    float vol = analogRead(VOLUME_POT);
    mixer1.gain(0, vol / 1024.0f);
  }
}


void loop() {
  playFile("SDTEST1.RAW");  // filenames are always uppercase 8.3 format
  delay(500);
  playFile("SDTEST2.RAW");
  delay(500);
  playFile("SDTEST3.RAW");
  delay(500);
  playFile("SDTEST4.RAW");
  delay(1500);
}

Thank you for posting this! I'm really surprised how hard it's been to find a working example of this setup, given how seeming useful the Prop Shield is. So, I looked through the code, removed the volume stuff (for now) and have tested it. It seems to play fine, but just like with everything else I've tried, I get NO SOUND AT ALL.
I thought it was my code, but now I'm thinking that I'm missing something else.
I'm using TeensyTransfer to move a file (16 bit RAW, all uppercase filename) to the flash, and it reads it fine via the terminal.

What else am I missing? I've got a simple 8-ohm speaker hooked up but am getting nothing.
Anyone have any ideas of what I should be looking for? I'm totally stumped.
 
What else am I missing? .... I'm totally stumped.

I'm totally stumped too, because I can't see what you've done. We have the "forum rule" (in red, at the top of every page) so your message can have enough info that we can help you. It's probably something simple, but nobody can see the problem if you hide the complete info.

Please, post the exact code you're running, and a photo of how you've connected things.
 
I'm totally stumped too, because I can't see what you've done. We have the "forum rule" (in red, at the top of every page) so your message can have enough info that we can help you. It's probably something simple, but nobody can see the problem if you hide the complete info.

Please, post the exact code you're running, and a photo of how you've connected things.

I apologize, I quoted the code above because I copiedand pasted it into my editor (changed the audio file name) and wasn't working. I'll repost my code when I can get back to the machine.
 
Here's the code I'm running and a photo of the setup.
IMG_0284.jpg

Code:
// Converted from the WavFilePlay from the Teensy release:
// hardware/teensy/avr/libraries/Audio/examples/WavFilePlayer/WavFilePlayer.ino
//
// Simple RAW file player example for the prop shield to use the Analog DAC
// and prop shield amplifier to play mono sounds.
//         [URL]http://www.pjrc.com/teensy/gui/?info=AudioOutputAnalog[/URL]
//
// On the prop shield, pin 6 selects the serial flash memory controller,
// and pin 5 enables the amplifier.
//
// This example code is in the public domain.


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


// GUItool: begin automatically generated code
AudioPlaySerialflashRaw  playFlashRaw1;  //xy=149,388
AudioMixer4              mixer1;         //xy=445,386
AudioOutputAnalog        dac1;           //xy=591,379
AudioConnection          patchCord1(playFlashRaw1, 0, mixer1, 0);
AudioConnection          patchCord2(mixer1, dac1);
// GUItool: end automatically generated code


#define PROP_AMP_ENABLE    5
#define FLASH_CHIP_SELECT 6


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


  // wait up to 3 seconds for the Serial device to become available
  long unsigned debug_start = millis ();
  while (!Serial && ((millis () - debug_start) <= 3000))
    ;


  Serial.println ("Start prop shield RAW player");


  // Enable the amplifier on the prop shield
  pinMode(PROP_AMP_ENABLE, OUTPUT);
  digitalWrite(PROP_AMP_ENABLE, HIGH);


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


  // Set initial volume
  // mixer1.gain(0, 0.5f);


  // uncomment these lines if you have a potentiometer or trimpot
  // on the pin A1 to control the volume, and comment out the
  // above line
  //float vol = analogRead(VOLUME_POT);
  mixer1.gain(0, 10.0f);


  // Start SerialFlash
  if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
    while (1)
      {
  Serial.println ("Cannot access SPI Flash chip");
  delay (1000);
      }
  }
}


void playFile(const char *filename)
{
  Serial.print("Playing file: ");
  Serial.println(filename);


  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playFlashRaw1.play(filename);


  // A brief delay for the library read RAW info
  delay(5);
}




void loop() {
  playFile("FX4.RAW");  // filenames are always uppercase 8.3 format
  delay(1500);
}
 

Attachments

  • IMG_0285.jpg
    IMG_0285.jpg
    171 KB · Views: 190
Looks like it ought to work, if the file really is on the flash chip.

Can you run File > Examples > SerialFlash > ListFiles and post the results you see in the serial monitor? Don't forget to edit the pin numbers to match your hardware.
 
Ummm, your pictures don't show that the DAC pin is connected between the Teensy and the Prop Shield. This pin is on the back of the Teensy, next to pin 13. The DAC pin is connected to the amplifier, and is how the prop shield makes sounds.
 
Good prompt MichaelM - I spent my Prop time with Talkie and some DotStars with 9DOF. Ordered a pair of the Prop_LC's with my Audio Kit - now I know why. I'll have to see about re-writing my FFT/TFT sample on the Prop Shield. I missed this part about Audio Library functions working from the DAC:

With Teensy 3.2, the Teensy Audio Library can be used to create sounds. Nearly all the audio library examples are designed for the Audio Shield. To adapt them for the Prop Shield, replace "i2s1" with "dac1" in the Design Tool, or AudioOutputI2S with AudioOutputAnalog in the Arduino code. Then delete the SGTL5000 object and any code which uses it.

For the samples in the Audio Tutorial - they could all (except for the mic input) be written and done with the Prop Shield once the sound files are stored on the 8MB flash?
 
For the samples in the Audio Tutorial - they could all (except for the mic input) be written and done with the Prop Shield once the sound files are stored on the 8MB flash?
Note, the prop shield is mono, while the audio shield is stereo. So if you have stereo sounds, you need to use a mixer to blend both channels at 50%.
 
Good Info - Most of the samples feed to a mixer IIRC so those would need to be adjusted. PlayMem and Raw seem to be mono but stereo from the SD card.

With proper input the ADC could bring in a mic.
 
Ummm, your pictures don't show that the DAC pin is connected between the Teensy and the Prop Shield. This pin is on the back of the Teensy, next to pin 13. The DAC pin is connected to the amplifier, and is how the prop shield makes sounds.

Yup, that was one problem for sure. I should have caught that but I think I looked at the image at http://www.pjrc.com/store/prop_shield.html under Audio Amplifier and just subconsciously didn't add those headers since they weren't in that photo. I should have thought through it.
So, I;ve added them now, and it makes a clicking noise when the sound should be playing, but the actual sound is coming through correctly. Anything else obvious that I'm missing?
Thank you guys!!
 
Status
Not open for further replies.
Back
Top