Ok, I’ve been wrestling with this all weekend, and I can only conclude that somehow I’m not accessing the system sound player correctly. Just wondering if any coding wizards might be able to spot where I’m going wrong.
The Challenge
I’ve set up array switching which works great, and currently plays the bladein.wav file on every switch. What I want is the system to play unique array idents from the common folder with every switch, so switching to Array 1 plays array1.wav, Array 2 plays array2.wav etc. I know I can fudge the functionality with prefont folders and various unique bladein.wav files, but that makes SD card management a bit clunky - a series of unique array.wav files all stored together in common is much tidier.
Of course this is a departure from the way ProffieOS normally handles sounds, because normally the system will randomly select, say, one clsh.wav from any number of clsh.wav files available. But in this instance, I want each numbered arrayX.wav to be locked to its associated numbered array.
So to get started, I borrowed this piece of code which I know works to play a ‘click’ wav file with every button press:
void PlaySound(const char* sound) {
RefPtr<BufferedWavPlayer> player = GetFreeWavPlayer();
if (player) {
if (!player->PlayInCurrentDir(sound)) player->Play(sound);
}
}
bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override {
switch (EVENTID(button, event, modifiers)) {
case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_ON):
case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_OFF):
case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_ON):
case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ANY_BUTTON | MODE_OFF):
SaberBase::RequestMotion();
PlaySound("press.wav");
return false;
case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_OFF):
case EVENTID(BUTTON_AUX, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON):
case EVENTID(BUTTON_AUX, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_OFF):
PlaySound("release.wav");
if (SaberBase::Lockup()) {
SaberBase::DoEndLockup();
SaberBase::SetLockup(SaberBase::LOCKUP_NONE);
return true;
} else {
return false;
}
case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ON):
case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_ON):
if (accel_.x < -0.15) {
pointing_down_ = true;
} else {
pointing_down_ = false;
}
return true;
And I peeled out the irrelevant bits and stitched it into this code which handles the array switching so this it would hopefully access the system player and play each respective arrayX.wav with every array switch:
#ifdef SABERSENSE_ARRAY_SELECTOR
#ifndef SABERSENSE_NUM_ARRAYS // No default number of arrays - must be defined in config.
#error "SABERSENSE_NUM_ARRAYS must be defined in the config file."
#endif
// Function to play the corresponding sound.
void PlaySound(const char* sound) {
RefPtr<BufferedWavPlayer> player = GetFreeWavPlayer();
if (player) {
if (!player->PlayInCurrentDir(sound)) {
player->Play(sound); // Fallback if not found in the current directory.
}
}
}
struct SabersenseArraySelector {
static int return_value; // Tracks the current array index.
static const int sabersense_num_arrays = SABERSENSE_NUM_ARRAYS;
float id() {
return return_value;
}
static void playArraySound(int arrayIndex) {
// Determine the sound file based on the array index.
const char* soundFile = nullptr;
switch (arrayIndex) {
case 0:
soundFile = "array1.wav";
break;
case 1:
soundFile = "array2.wav";
break;
case 2:
soundFile = "array3.wav";
break;
case 3:
soundFile = "array4.wav";
break;
case 4:
soundFile = "array5.wav";
break;
case 5:
soundFile = "array6.wav";
break;
case 6:
soundFile = "array7.wav";
break;
case 7:
soundFile = "array8.wav";
break;
case 8:
soundFile = "array9.wav";
break;
default:
return; // No sound for invalid array index.
}
// Play the corresponding sound file using the PlaySound function.
PlaySound(soundFile); // Calls your custom PlaySound function.
}
static void cycle() {
return_value = (return_value + 1) % sabersense_num_arrays;
playArraySound(return_value); // Play the sound corresponding to the current array.
}
};
int SabersenseArraySelector::return_value = 0; // Start with the first array (index 0).
#undef BLADE_ID_CLASS_INTERNAL
#define BLADE_ID_CLASS_INTERNAL SabersenseArraySelector
#undef BLADE_ID_CLASS
#define BLADE_ID_CLASS SabersenseArraySelector
#endif
With the event handled like this:
// BladeID and manual blade array selector.
case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF):
#ifdef SABERSENSE_ARRAY_SELECTOR
// Cycles through blade arrays regardless of BladeID status.
SabersenseArraySelector::cycle();
FindBladeAgain();
SaberBase::DoBladeDetect(true);
return true;
#else
// Runs BladeID manually to actually check BladeID status.
// Won't change arrays unless status tells it to (i.e. Data/Neg resistance changes).
FindBladeAgain();
SaberBase::DoBladeDetect(true);
return true;
#endif
Now by rights, I make it that it should play both bladein.wav and the new array.wav files with every switch. (I know that’s a conflict, but one step at a time). But although it all compiles and loads up successfully, and it does the array switch correctly, it doesn’t play the array.wav files, only the bladein files.
I’ve tried all sorts of different combos, but I just can’t nail it.
As such, any thoughts welcome.
Thanks in advance.