I found this sketch that does what I want...which is to switch between mic input and the wav files on the SD card. Pardon my coding ignorance, but I'm having trouble figuring out how it works.
It has various logic to set the mode variable, and then updates various mixer gains dependent on the mode.
// Audio Tutorial Kit Tester
//
// http://www.pjrc.com/store/audio_tutorial_kit.html
//
// Easily test all the tutorial hardware by only listening and pressing buttons.
// 1: listen for microphone (any button press moves to #2)
// 2: listen for SD card playing (any button press moves to #2)
// 3: test 3 buttons and 3 knobs (press all 3 buttons to go back to step #1)
//
// After test is completed, EEPROM storage is used to remember the hardware is good
// Good hardware will begin at #3, which corresponds to the first tutorial example
#include <Audio.h>
#include <SD.h>
#include <Bounce.h>
#include <EEPROM.h>
#include "AudioSampleButton1.h"
#include "AudioSampleButton2.h"
#include "AudioSampleButton3.h"
#include "AudioSampleKnob1.h"
#include "AudioSampleKnob2.h"
#include "AudioSampleKnob3.h"
#include "AudioSampleNosdcard.h"
AudioInputI2S i2s1;
AudioSynthWaveform waveform1;
AudioPlaySdWav playSdWav1;
AudioPlayMemory sample1;
AudioMixer4 mixer1;
AudioMixer4 mixer2;
AudioOutputI2S i2s2;
AudioConnection patchCord1(i2s1, 0, mixer1, 0);
AudioConnection patchCord2(i2s1, 0, mixer2, 0);
AudioConnection patchCord3(playSdWav1, 0, mixer1, 1);
AudioConnection patchCord4(playSdWav1, 1, mixer2, 1);
AudioConnection patchCord5(waveform1, 0, mixer1, 2);
AudioConnection patchCord6(waveform1, 0, mixer2, 2);
AudioConnection patchCord7(sample1, 0, mixer1, 3);
AudioConnection patchCord8(sample1, 0, mixer2, 3);
AudioConnection patchCord9(mixer1, 0, i2s2, 0);
AudioConnection patchCordA(mixer2, 0, i2s2, 1);
AudioControlSGTL5000 sgtl5000_1;
Bounce button0 = Bounce(0, 15);
Bounce button1 = Bounce(1, 15);
Bounce button2 = Bounce(2, 15);
// 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
int mode;
int count = 1;
int a1 = 0, a2 = 0, a3 = 0;
bool anybutton = false;
bool sdcardinit = true;
bool playsamples = false;
void setup() {
mode = EEPROM.read(400);
AudioMemory(20);
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
Serial.begin(115200);
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
sgtl5000_1.micGain(36);
mixer1.gain(0, 0);
mixer1.gain(1, 0);
mixer1.gain(2, 0);
mixer1.gain(3, 0.4);
mixer2.gain(0, 0);
mixer2.gain(1, 0);
mixer2.gain(2, 0);
mixer2.gain(3, 0.4);
waveform1.begin(WAVEFORM_SINE);
delay(1000);
button0.update();
button1.update();
button2.update();
a1 = analogRead(A1);
a2 = analogRead(A2);
a3 = analogRead(A3);
}
void update() {
static int state = 0;
button0.update();
button1.update();
button2.update();
anybutton = false;
if (button0.fallingEdge()) {
anybutton = true;
Serial.println("Button (pin 0) Press");
if (playsamples) sample1.play(AudioSampleButton1);
}
if (button1.fallingEdge()) {
anybutton = true;
Serial.println("Button (pin 1) Press");
if (playsamples) sample1.play(AudioSampleButton2);
}
if (button2.fallingEdge()) {
anybutton = true;
Serial.println("Button (pin 2) Press");
if (playsamples) sample1.play(AudioSampleButton3);
}
if (button0.risingEdge()) {
Serial.println("Button (pin 0) Release");
}
if (button1.risingEdge()) {
Serial.println("Button (pin 1) Release");
}
if (button2.risingEdge()) {
Serial.println("Button (pin 2) Release");
}
if (state == 0) {
int a = analogRead(A1);
if (a > a1 + 50 || a < a1 - 50) {
Serial.print("Knob (pin A1) = ");
Serial.println(a);
if (playsamples && !sample1.isPlaying()) sample1.play(AudioSampleKnob1);
a1 = a;
}
state = 1;
}
else if (state == 1) {
int a = analogRead(A2);
if (a > a2 + 50 || a < a2 - 50) {
Serial.print("Knob (pin A2) = ");
Serial.println(a);
if (playsamples && !sample1.isPlaying()) sample1.play(AudioSampleKnob2);
a2 = a;
}
state = 2;
}
else {
int a = analogRead(A3);
if (a > a3 + 50 || a < a3 - 50) {
Serial.print("Knob (pin A3) = ");
Serial.println(a);
if (playsamples && !sample1.isPlaying()) sample1.play(AudioSampleKnob3);
a3 = a;
}
state = 0;
}
}
elapsedMillis msec = 0;
void loop() {
update();
// Test microphone
if (mode == 255) {
playsamples = true;
mixer1.gain(0, 1.0);
mixer2.gain(0, 1.0);
if (anybutton) {
mixer1.gain(0, 0);
mixer2.gain(0, 0);
if (sdcardinit) {
if (!(SD.begin(SDCARD_CS_PIN))) {
while (1) {
Serial.println("Unable to access the SD card");
if (playsamples) sample1.play(AudioSampleNosdcard);
delay(3500);
}
}
sdcardinit = false;
}
mode = 123;
}
// Play WAV file (test SD card, sound quality)
}
else if (mode == 123) {
mixer1.gain(1, 0.75);
mixer2.gain(1, 0.75);
if (playSdWav1.isPlaying() == false) {
Serial.println("Start playing");
playSdWav1.play("SDTEST2.WAV");
delay(10); // wait for library to parse WAV info
}
if (anybutton) {
playSdWav1.stop();
mixer1.gain(1, 0);
mixer2.gain(1, 0);
mode = 45;
EEPROM.write(400, mode);
}
// Beeping (test buttons & knobs)
}
else {
mixer1.gain(2, 1.0);
mixer2.gain(2, 1.0);
if (mode == 45) {
Serial.print("Beep #");
Serial.println(count);
count = count + 1;
waveform1.frequency(440);
waveform1.amplitude(0.35);
msec = 0;
mode = 46;
}
else if (mode == 46) {
if (msec > 250) {
waveform1.amplitude(0);
msec = 0;
mode = 47;
}
}
else {
if (msec > 1750) {
mode = 45;
}
}
if (button0.read() == LOW && button1.read() == LOW && button2.read() == LOW) {
mixer1.gain(2, 0);
mixer2.gain(2, 0);
mode = 255;
}
}
}
/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your Arduino
model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
modified 8 May 2014
by Scott Fitzgerald
modified 2 Sep 2016
by Arturo Guadalupi
modified 8 Sep 2016
by Colby Newman
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Blink
*/
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
It has various logic to set the mode variable, and then updates various mixer gains dependent on the mode.
I did post the code in between the code things...it must have been something with my browser blocking it.
test
Code:/* Blink Turns an LED on for one second, then off for one second, repeatedly. Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to the correct LED pin independent of which board is used. If you want to know what pin the on-board LED is connected to on your Arduino model, check the Technical Specs of your board at: https://www.arduino.cc/en/Main/Products modified 8 May 2014 by Scott Fitzgerald modified 2 Sep 2016 by Arturo Guadalupi modified 8 Sep 2016 by Colby Newman This example code is in the public domain. http://www.arduino.cc/en/Tutorial/Blink */ // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }
I do get that generally how it works, although I'm having trouble simplifying it...
// Advanced Microcontroller-based Audio Workshop
//
// http://www.pjrc.com/store/audio_tutorial_kit.html
// https://hackaday.io/project/8292-microcontroller-audio-workshop-had-supercon-2015
//
// Part 2-2: Mixers & Playing Multiple Sounds
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioPlaySdWav playSdWav1; //xy=89,32
AudioPlaySdWav playSdWav2; //xy=89,108
AudioMixer4 mixer2; //xy=268,123
AudioMixer4 mixer1; //xy=279,50
AudioOutputI2S i2s1; //xy=537,49
AudioConnection patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection patchCord2(playSdWav1, 1, mixer2, 0);
AudioConnection patchCord3(playSdWav2, 0, mixer1, 1);
AudioConnection patchCord4(playSdWav2, 1, mixer2, 1);
AudioConnection patchCord5(mixer2, 0, i2s1, 1);
AudioConnection patchCord6(mixer1, 0, i2s1, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=469,142
// GUItool: end automatically generated code
// 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
int analogThreshold = 512;
void setup() {
Serial.begin(9600);
AudioMemory(8);
sgtl5000_1.enable();
sgtl5000_1.volume(0.8);
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
pinMode(13, OUTPUT); // LED on pin 13
mixer1.gain(0, 0.5);
mixer1.gain(1, 0.5);
mixer2.gain(0, 0.5);
mixer2.gain(1, 0.5);
delay(1000);
}
void loop() {
if (playSdWav1.isPlaying() == false) {
Serial.println("Start playing 1");
playSdWav1.play("CM.000.WAV");
delay(10); // wait for library to parse WAV info
}
if (playSdWav2.isPlaying() == false) {
Serial.println("Start playing 2");
playSdWav2.play("SDTEST1.WAV");
delay(10); // wait for library to parse WAV info
}
// uncomment this code to allow Knob A3 to pan between songs
// int knob = analogRead(A3); // knob = 0 to 1023
// float gain1 = (float)knob / 1023.0;
// float gain2 = 1.0 - gain1;
// mixer1.gain(0, gain1);
// mixer1.gain(1, gain2);
// mixer2.gain(0, gain1);
// mixer2.gain(1, gain2);
int knob = analogRead(A3); // knob = 0 to 1023
float gain1 = (knob <= analogThreshold);
float gain2 = (knob >= analogThreshold);
mixer1.gain(0, gain1);
mixer1.gain(1, gain2);
mixer2.gain(0, gain1);
mixer2.gain(1, gain2);
}
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioInputI2S i2s1; //xy=196,92
AudioPlaySdWav playWav1; //xy=214,43
AudioMixer4 mixer2; //xy=379,222
AudioMixer4 mixer1; //xy=386,121
AudioOutputI2S i2s2; //xy=559,86
AudioConnection patchCord1(i2s1, 0, mixer1, 1);
AudioConnection patchCord2(i2s1, 0, mixer2, 1);
AudioConnection patchCord3(playWav1, 0, mixer1, 0);
AudioConnection patchCord4(playWav1, 1, mixer2, 0);
AudioConnection patchCord5(mixer2, 0, i2s2, 1);
AudioConnection patchCord6(mixer1, 0, i2s2, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=553,148
// GUItool: end automatically generated code
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
void setup() {
Serial.begin(9600);
AudioMemory(8);
sgtl5000_1.enable();
sgtl5000_1.volume(0.7);
sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
sgtl5000_1.micGain(40);
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);
}
mixer1.gain(0, 0.5);
mixer1.gain(1, 0.5);
mixer2.gain(0, 0.5);
mixer2.gain(1, 0.5);
}
}
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(25);
// 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;
sgtl5000_1.volume(vol);
}
}
void loop() {
playFile("CM.000.WAV"); // filenames are always uppercase 8.3 format
delay(500);
// playFile("SDTEST2.WAV");
// delay(500);
// playFile("SDTEST3.WAV");
// delay(500);
// playFile("SDTEST4.WAV");
// delay(1500);
}
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>
// create audio component objects
AudioPlaySdWav playWav1; // SD card wav file player
AudioInputI2S audioInput; // audio shield input, mic or line-in selectable
AudioMixer4 mixer1; // mixers to combine wav file and audio shield inputs
AudioMixer4 mixer2;
// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
AudioOutputI2S audioOutput;
//AudioOutputSPDIF audioOutput;
//AudioOutputAnalog audioOutput;
// wire up the interfaces between audio components with patch cords
// mixer inputs
AudioConnection patchCord1(playWav1, 0, mixer1, 0); // left channels into mixer 1
AudioConnection patchCord2(audioInput, 0, mixer1, 1);
AudioConnection patchCord3(playWav1, 1, mixer2, 0); // right channels into mixer 2
AudioConnection patchCord4(audioInput, 1, mixer2, 1);
// mixer outputs
AudioConnection patchCord5(mixer1, 0, audioOutput, 0);
AudioConnection patchCord6(mixer2, 0, audioOutput, 1);
// object to allow control of the SGTL5000 audio shield settings
AudioControlSGTL5000 audioShield;
// buttons and potentiometers
#define pot0 A1
#define pot1 A2
#define pot2 A3
#define button0 0
#define button1 1
#define button2 2
//#define button3 27
// attach button debouncers to input buttons
Bounce db_button0 = Bounce(button0, 30);
Bounce db_button1 = Bounce(button1, 30);
Bounce db_button2 = Bounce(button2, 30);
//Bounce db_button3 = Bounce(button3, 30);
// choose mic or line input for audio shield input path
const int inputChSelect = AUDIO_INPUT_MIC;
//const int inputChSelect = AUDIO_INPUT_LINEIN;
// audio shield volume
int masterVolume = 0;
// uncomment one set of SD card SPI pins to use
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
// wav filenames on SD card for playback
char *wavFiles[] = {"CM.000.WAV", "SDTEST1.WAV", "SDTEST2.WAV", "SDTEST3.WAV", "SDTEST4.WAV"};
byte wavNum = 0; // current wav file index playing from array list
bool wavIsPlaying = false; // track if a wav file is currently playing or not
void setup() {
Serial.begin(9600);
Serial.println("SD Player Demo\n");
// buttons are inputs with pullups
pinMode(button0, INPUT_PULLUP);
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
//pinMode(button3, INPUT_PULLUP);
// 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.
Serial.print("init audio shield...");
audioShield.enable();
audioShield.inputSelect(inputChSelect); // select mic or line-in for audio shield input source
audioShield.volume(0.5);
Serial.println("done.");
mixer1.gain(0, 0.5);
mixer1.gain(1, 0.5);
mixer1.gain(2, 0);
mixer1.gain(3, 0);
mixer2.gain(0, 0.5);
mixer2.gain(1, 0.5);
mixer2.gain(2, 0);
mixer2.gain(3, 0);
Serial.print("init SD card...");
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
// stop here, but print a message
Serial.println("Unable to access the SD card. Program halted.");
while (1);
}
Serial.println("done.");
Serial.println("Waiting for control input...");
// reset audio resource usage stats.
// useful if tracking max usage in main program
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}
void playFile(const char *filename)
{
Serial.print("Start playing file: ");
Serial.println(filename);
// start playing the file.
// sketch continues to run while the file plays.
playWav1.play(filename);
// A brief delay for the library to read WAV header info
delay(5);
}
void loop() {
// auto select next wav file if current file finishes playing
// and if playback is enabled
if ((!(playWav1.isPlaying())) && (wavIsPlaying)) {
wavNum++;
if (wavNum > 4) {
wavNum = 0;
}
playFile(wavFiles[wavNum]);
}
// read volume control pot and set audio shield volume if required
int vol = analogRead(pot0);
if (vol != masterVolume) {
masterVolume = vol;
audioShield.volume((float)vol / 1023); // audio shield headphone out volume (optional)
mixer1.gain(0, (float)vol / 1023); // software mixer input channel volume
mixer1.gain(1, (float)vol / 1023);
mixer2.gain(0, (float)vol / 1023);
mixer2.gain(1, (float)vol / 1023);
}
// update the button debounce status so falling edges
// can be detected and processed
db_button0.update();
db_button1.update();
db_button2.update();
//db_button3.update();
// button 0 pressed - toggle playback start/stop for current wav file
if (db_button0.fallingEdge()) {
if (playWav1.isPlaying()) {
playWav1.stop();
wavIsPlaying = false;
Serial.println("Playback stopped\n");
}
else {
playFile(wavFiles[wavNum]);
wavIsPlaying = true;
Serial.println("Playback started");
}
//Serial.print("Audio memory usage max: ");
//Serial.println(AudioMemoryUsageMax());
}
// button 1 pressed - skip track forward
if (db_button1.fallingEdge()) {
Serial.println("Skip track forward");
if (wavNum == 4)
wavNum = 0;
else
wavNum++;
playFile(wavFiles[wavNum]);
wavIsPlaying = true;
}
// button 2 pressed - skip track backward
if (db_button2.fallingEdge()) {
Serial.println("Skip track backward");
if (wavNum == 0)
wavNum = 4;
else
wavNum--;
playFile(wavFiles[wavNum]);
wavIsPlaying = true;
}
}
You seem to be turning wav file volume on at the same time as microphone volome on, rather than cross-fading -
I thought you wanted to cross-fade between them?
That's what I mean - in software you can crossfade instantly as well as gradually.Well, not crossfade so much...what I wanted it to do is to be able to switch between the mic input and the wav files on the SD card.