Making modes to referring different sound file arrays

Hi everyone,

Sorry for the title, I found it hard to explain what I'm trying to figure, as perhaps arrays aren't the right wording (or requirement).

I have a device I made for my son which has 4 buttons: red, white, blue and green. (he is 18 months old).

I have these programmed using an adafruit audio fx board to play sounds when a button is pressed:

sfx.playTrack("COWABUNGWAV");

Anyway, I have now added a potentiometer which can be moved to select 1 of 3 modes in the system, therefore allowing me to program 12 sounds and thus make the toy help him develop more words.

The sounds I have are:

Colours, Sayings and TMNT (ninja turtle sounds).

What I want is:
When he presses a button, check which mode is selected, then choose the correct sound for the appropriate mode and button.

eg. RED = sound 1
White = sound 2
Green = sound 3
Blue = sound 4
(of that mode).

SO i have created some arrays:

char modes[3] = {"Colours","Sayings"."TMNT"};

char TMNT[3] = {"COWABUNGWAV","THEME   WAV","WASFUN  WAV"};

And below is the code currently used to trigger the sound:

[code]if (digitalRead(butRed) == LOW) {
    loopsStill = 0;
    sfx.playTrack("COWABUNGWAV");


    Serial.println("RED Playing");
  }

So I want something like...

sfx.playTrack(modes[curmode][1])

Now I'm aware this code is probably all kinds of wrong but I'm too new to really understand where to go from here.

Pretty much I want it to:

  • See that btnRED is LOW (working)
  • Check which mode is selected
  • Play the sound number for that button (btnRED = 1) for that mode.

Therefore, Mode 1 = Colours, btnRED = button1 , so mode 1, song 1 = "COWABUNGAWA"
..

Any help here would be amazing. I'm sure there is a way to do it.

My other option is doing in each button statement:

IF mode = X THEN play song = Y (that idea but obviously correct programming code)

but I would like to have it more advanced mainly so I learn a better way to do things!

So I want something like...

Sounds good. Except that you are dereferencing a 2D array, while the array is actually a 2D array of nonsense. A char array can not hold multiple strings.

Where is curmode set? What is the significance of the 1?

hmm ok thanks for the response.

curmode is set from the potentiometer.
I could set this to anyhting I guess..
Perhaps i could just set it to the string that is needed.

eg. Curmode = "Colours"

Thats one step out of the way.

So what I'm thinking is i can have the same code for all buttons now:

sfx.playTrack(curMode[curButton])

I can then do

If butRED == LOW then
curButton = 1
end if

So each button press will just set the curButton variable and then when it runs over the playtrack code it will know the curButton.

But can a variable curMode which is actually the string "Colours" read the array "colours"...

This is the bit that broke my head. lol

The idea came to me from this guys Scareduino:
Scareduino youtube vid

WHich he sets an array of the sound files and then calls them from the arry.

I'm doing exactly this however I have 3 different arrays that I want to use depending upon the mode setting.

Worse case scenario I can just have the arrays like he has and then under each button just do an IF and THEN situation which checks the mode and then plays the correct array sound..
Just doesnt seem as snazzy and is 4 x as much code.

char modes[3] = {'Colours',
                'Sayings',
                'TMNT'
                };

 char Colours[4] =  {'RED     WAV',
                     'WHITE   WAV',
                     'GREEN   WAV',
                     'BLUE    WAV'
                    };
                    
 char TMNT[3] = {'COWABUNGWAV',
                 'THEME   WAV',
                 'WASFUN  WAV'
                 };
                 
 char Sayings[4] = {'STOP    WAV',
                    'GOGOGO  WAV',
                    'NEENAW  WAV',
                    'PEEKABOOWAV'
                   };

Please post your complete current code.

char modes[3] = char modes[3] = {'Colours',
                'Sayings',
                'TMNT'
                };

Single quotes are for single characters. Can you post a picture of your keyboard with the Colours key circled?

You are trying to stuff strings in a char array. You need either an array of pointers or a 2D array of chars.

char *modes[3] = { "Colours", "Sayings", "TMNT" };

or

char modes[8][3] = { "Colours", "Sayings", "TMNT" };

Given curButton and curMode you can use a single array of wav names and simply derive the index of the desired file from them. Something like:

index=(curMode-1)*NoButtons+curButton-1;

EDIT: ITS WORKING with the below code, but replacing the ' with " as mentioned above.
So in reality, is this "clean enough" or should i try something else. The switch is all good if it's an ok route to go down.

wowza, ok ill post my current code.

Obviously I have no idea what I'm doing as there are array features that I am not doing right I guess.

Thanks for the responses.

char *Colours[4] =  {"RED     WAV",
                     "WHITE   WAV",
                     "GREEN   WAV",
                     "BLUE    WAV"
                    };
                    
 char *TMNT[3] = {"COWABUNGWAV",
                 "THEME   WAV",
                 "WASFUN  WAV"
                 };
                 
 char *Sayings[4] = {"STOP    WAV",
                    "GOGOGO  WAV",
                    "NEENAW  WAV",
                    "PEEKABOOWAV"
                   };


void loop () {
buttonPressed = false;

//Check mode.  Saves variable curMode (1,2,3) 
checkMode();


if (digitalRead(butRed) == LOW) {
    
    curButton = 1;
    buttonPressed = true;
    
    Serial.println("RED Playing");
  }


if (buttonPressed == true){
  Serial.println("noted Pressed");
  switch(curMode){
      case 1:
      sfx.playTrack(Colours[curButton]);
      Serial.println(curButton);
      Serial.println(Colours[curButton]);
      
      break;

      case 2:
      sfx.playTrack(Sayings[curButton]);
      break;

      case 3:
      sfx.playTrack(TMNT[curButton]);
      break;

      default:
      sfx.playTrack(Colours[curButton]);
      break;
  }

Now I think I'm getting there, even though it isnt as elegant as I could get.

The thing here is that on the serial:

curButton = 1 (good)
Colours[curButton] = ⸮p>⸮!9⸮ (not good)

SO I'm getting where I want in the code suing my mode and cutButton variables, and I'm happy to use this SWITCH statement, however it seems that Colours[curButton] doesn't return that text string like it does for the dude with the scareduino.

(his code below)

#define NUM_SOUNDS 5
// The names of the found files.
// Note that they are 8 characters followed by a 3 character file
// type (.OGG or .WAV). Spaces are inserted to make up the
// 8 characters as needed.
char *soundName[NUM_SOUNDS] = {
  "HI_GANG OGG",
  "GROWL   OGG",
  "GHOSTOOOOGG",
  "SCREAMHPOGG",
  "ILBEBACKOGG"
};


int currentSound = 0;




void loop()
{
  // get the control switch's position
  currentSwitch = debounce(lastSwitch);


      sfx.playTrack(soundName[currentSound]);

Single quotes are STILL for single characters. Do you know what SINGLE means?

Is there some reason you can't post YOUR COMPLETE code?

gfvalvo:
Is there some reason you can't post YOUR COMPLETE code?

I am limited by the 9000 character max post so my entire code doesn't fit in here even in code tags.
I put in the parts that related to this, because it's formatted poorly, and contains a bunch of stuff unrelated to my issue, but i can understand why you want to see it all.

PaulS:
Single quotes are STILL for single characters. Do you know what SINGLE means?

Yes sorry, I have corrected my quotes and that is what made it work with my newest code. thanks for that. I'll have to find this other post that I was looking at that someone said not to use double quotes in an array (and it was strings like mine!). I originally had doubles and moved to singles just before posting on here.

gangel77:
I am limited by the 9000 character max post so my entire code doesn’t fit in here even in code tags.
I put in the parts that related to this, because it’s formatted poorly, and contains a bunch of stuff unrelated to my issue, but i can understand why you want to see it all.

An important technique for getting good help that you should learn is creating an MCVE.

This is the smallest complete program that correctly compiles and demonstrates your problem. People are much more inclined to help if they don’t have to wade through dozens or hundreds of lines of irrelevant, mess, ugly code in order to diagnose your problem. An MCVE is infinitely better to work with than code snippets that won’t compile.

Regarding your project, I’d probably go with a 2-Dimensional array of character pointers:

const uint8_t numModes = 3;
const uint8_t numSoundsPerMode = 4;

const char * const sounds[numModes][numSoundsPerMode] = {
  {"RED     WAV", "WHITE   WAV", "GREEN   WAV", "BLUE    WAV"},
  {"COWABUNGWAV", "THEME   WAV", "WASFUN  WAV", nullptr},
  {"STOP    WAV", "GOGOGO  WAV", "NEENAW  WAV", "PEEKABOOWAV"}
};

void setup() {
  Serial.begin(115200);
  delay(1000);

  for (uint8_t i = 0; i < numModes; i++) {
    for (uint8_t j = 0; j < numSoundsPerMode; j++) {
      Serial.print(sounds[i][j]);
      if (j < numSoundsPerMode - 1) {
        Serial.print(",  ");
      }
    }
    Serial.println();
  }
}

void loop() {}

Note that because one of your modes only has 3 entries while the others have 4, I inserted a null pointer as a place holder. Depending on how your ‘sfx.playTrack()’ method handles being passed a nullptr, you may want to trap it.

gfvalvo:
An important technique for getting good help that you should learn is creating an MCVE.

Fantastic, thanks for that.