What I’m trying to do is start multiple tracks at the same time, by triggering one input, but instead of sending the tracks to adjacent outputs (like what happens using synced set), I want the tracks to be sent all to the same output.
The idea is to create a “noisy environment” consisting out of several types of sounds / noise and then being able to turn on and off specific sounds (preferably fading them in and out).
Is this possible?
I think you need to see this. Tsunami Super WAV Trigger one button plays 4 outputs
Thanks, but that plays multiple tracks from as many seperate outputs. I want all the tracks to play simultanously from one output.
If you peruse that link or its guide there are a few ways to accomplish this; in that linked thread the designer of the product suggests using ‘synced set’ setting via the configurator app
As I stated in my opening post and my answer to dilshana, that function doesn’t do what I’m trying to create. From the post you both mentioned: “Synced Set” will trigger up to 8 (or 4 stereo) tracks (.wav files) and send them each to a different output.”
Ofcourse I have read the manual and wiring guide and I’ve searched the forum. It looks like it can be done using serial commands, but as that’s not my forte, I’m trying to find input from others who might be more knowleadgeble on the subject than I am.
Oh. Can you just run many output wires and join them together as one input?
Check out pg 7, you can ostenisbly use ‘output’ or ‘polyphony’ (see if those are selectable in the config app) to route them to the same output?
I would also note “Polyphony also affects how you handle volume. If you mix 4 tracks together that are all full-scale volume, the result will be clipped and distorted. In this case, it won’t help to lower the output gain setting since this only affects the final output stage – you’ll just lower the volume of an already clipped mix. You must reduce the volume of the WAV files themselves so that the resulting addition of the tracks does not clip.”
Believe me, I’ve tried everything using the configurator. That’s just not going to happen (unless I use one button connected to multiple inputs to start all the tracks and a button to a single input for every seperate track to stop it. Besides the fact that that would mean I would run out of available inputs pretty quickly, I can’t imagine that this would be a sustainable or even reliable solution.
From another post by the designer, I gathered it might be possible to “set up” the tracks I want to play and immediately pause playback using the CONTROL_TRACK command and then start them all at the same time using the RESUME_ALL_SYNC command. I guess I’ll have to see if I can get that to work. And if so, maybe incorporate the TRACK_FADE command to fade the separate tracks in and out.
In the meantime, I can just hope that someone can help me get started as, like I said, I’m not an avid coder and serial communication isn’t really straightforward for me. It would be nice to get some pointers from people who are better at that sort of thing.
There is no trigger function that will do what you want, and even if there was, you would still need serial communication of some sort to do any fading of individual tracks. If hooking up serial RX/TX and getting that working seems daunting, consider using Qwiic (I2C) instead. It’s a simple matter of connecting a pre-made cable, and the Qwiic Arduino Library has functions for everything you need.
I realized that after an afternoon of experimenting. It’s not that I don’t want to use serial communication, It’s just the fact that I’m not a programmer and I’m not sure if I’ve got the skill to achieve what I’m wanting to do, so I was looking for tips. Meanwhile, I’ve found the arduino example sketch and using that, the manual and chatgpt, came up with he following:
/*
Tsunami 3-Sound Recognition Game – Arduino Mega + Tsunami
HARDWARE
- Arduino Mega 2560 (5 V logic)
- Robertsonics Tsunami (3.3 V logic!)
- Arduino TX1 (pin 18) → level shifter → Tsunami RX
- Arduino RX1 (pin 19) ← Tsunami TX (3.3 V is safe)
- Common GND
- Buttons:
- 1x large START button → Mega pin 2 (active LOW, INPUT_PULLUP)
- 9x small GUESS buttons → Mega pins 22..30 (active LOW, INPUT_PULLUP)
Each button corresponds to one specific track number (1..9).- LED on pin 13 used as game status indicator.
- Audio: use Tsunami Output 1 (stereo pair index 0).
SD CARD SETUP
- Place 9 audio files in the root directory of the Tsunami microSD card.
- Filenames must begin with track numbers 1..9, e.g.:
1_cat.wav, 2_dog.wav, 3_bird.wav,
4_car.wav, 5_train.wav, 6_plane.wav,
7_bell.wav, 8_drum.wav, 9_horn.wav- The Tsunami indexes tracks by their numeric prefix.
GAME RULES
Press START → the game randomly picks 1 track from each of 3 categories:
Category A: tracks 1–3
Category B: tracks 4–6
Category C: tracks 7–9
→ 3 tracks total are played simultaneously (polyphonic) to Output 1.Player listens and presses GUESS buttons (1..9).
- If the guessed track is one of the active three:
→ that track fades out smoothly over 3 seconds and stops.- If not active: nothing happens (no penalty).
When all three tracks are correctly guessed:
→ game stops all tracks and resets to idle state.
→ LED blinks slowly in idle mode, faster in play mode.NOTES
- Track start gain is set to –10 dB to avoid clipping when mixing.
- Fade-out uses Tsunami TRACK_FADE command: target –70 dB in 3000 ms.
- Random seed is taken from analog input A0.
- Adjust button pin numbers or category definitions as needed.
*/#include <Tsunami.h>
// ---------- Pin configuration ----------
const uint8_t LED_PIN = 13;
const uint8_t START_BTN_PIN = 2; // large start button (active-LOW)// 9 small buttons, each for a track 1..9 (adjust pin mapping as needed)
const uint8_t GUESS_BTN_PINS[9] = {
22,23,24,25,26,27,28,29,30
};// ---------- Game configuration ----------
const uint8_t TRACKS_CAT_A[3] = { 1, 2, 3 };
const uint8_t TRACKS_CAT_B[3] = { 4, 5, 6 };
const uint8_t TRACKS_CAT_C[3] = { 7, 8, 9 };// Adjust fade times and gain levels here
const int16_t START_TRACK_GAIN_DB = -10; // per-track gain at start (avoid clipping when mixing) [dB]
const int16_t CORRECT_TARGET_DB = -70; // fade target on correct guess [dB]
const uint16_t CORRECT_FADE_MS = 3000; // fade duration [ms]
const uint8_t OUTPUT_INDEX = 0; // stereo output 1 = 0 (mono 0..7, stereo 0..3)// Debounce settings
const uint16_t DEBOUNCE_MS = 25;// ---------- State ----------
enum GameState { IDLE, PLAYING };
GameState gameState = IDLE;uint8_t activeTracks[3] = {0,0,0}; // the 3 chosen tracks for this round
bool solved[3] = {false,false,false};unsigned long lastReadMsStart = 0;
unsigned long lastReadMsGuess[9] = {0};Tsunami tsunami;
// ---------- Helpers ----------
bool buttonPressed(uint8_t pin, unsigned long &lastMs) {
// simple poll + debounce for buttons with INPUT_PULLUP (active-LOW)
bool pressed = false;
if (digitalRead(pin) == LOW) {
unsigned long now = millis();
if (now - lastMs > DEBOUNCE_MS) {
// wait for release to avoid auto-repeat
while (digitalRead(pin) == LOW) { delay(1); }
lastMs = now;
pressed = true;
}
}
return pressed;
}void pickRound() {
// pick 1 random track from each category (no repetition inside a category)
activeTracks[0] = TRACKS_CAT_A[random(0,3)];
activeTracks[1] = TRACKS_CAT_B[random(0,3)];
activeTracks[2] = TRACKS_CAT_C[random(0,3)];solved[0] = solved[1] = solved[2] = false;
}int findActiveIndexForTrack(uint8_t trackNr) {
for (int i=0; i<3; i++) {
if (activeTracks[i] == trackNr) return i;
}
return -1;
}void startRoundPlayback() {
// Set per-track gain, play poly, and route all to the same output
for (int i=0; i<3; i++) {
uint16_t t = activeTracks[i];
tsunami.trackGain(t, START_TRACK_GAIN_DB); // set individual pre-mix gain
tsunami.trackPlayPoly(t, OUTPUT_INDEX, true); // play poly, lock voice = true
}
}void fadeOutCorrect(uint8_t trackNr) {
// Fade down to target gain and stop at end (stopFlag = true)
tsunami.trackFade(trackNr, CORRECT_TARGET_DB, CORRECT_FADE_MS, true);
}bool allSolved() {
return solved[0] && solved[1] && solved[2];
}void resetGameAudio() {
tsunami.stopAllTracks();
}// ---------- Arduino ----------
void setup() {
// Serial for debug (USB)
Serial.begin(115200);// Pins
pinMode(LED_PIN, OUTPUT);
pinMode(START_BTN_PIN, INPUT_PULLUP);
for (uint8_t i=0; i<9; i++) {
pinMode(GUESS_BTN_PINS[i], INPUT_PULLUP);
}// Tsunami startup (wait a bit after reset/power-up)
delay(1000);
tsunami.start(); // uses Serial1 @ 57600 by default
delay(10);// Clean start
tsunami.stopAllTracks();
tsunami.samplerateOffset(OUTPUT_INDEX, 0); // no pitch offset
tsunami.masterGain(OUTPUT_INDEX, 0); // master mix at 0 dB// Enable track reporting (handy, not strictly needed)
tsunami.setReporting(true);// random seed
randomSeed(analogRead(A0));Serial.println(F(“Tsunami game ready. Press START to begin.”));
}void loop() {
// Keep Tsunami status current
tsunami.update();// LED blinks slowly in IDLE, faster in PLAYING
static unsigned long lastBlink = 0;
static bool led = false;
if (millis() - lastBlink > (gameState == IDLE ? 500 : 100)) {
lastBlink = millis();
led = !led;
digitalWrite(LED_PIN, led ? HIGH : LOW);
}// START
if (gameState == IDLE) {
if (buttonPressed(START_BTN_PIN, lastReadMsStart)) {
pickRound();
startRoundPlayback();
gameState = PLAYING;Serial.print(F("Started tracks: ")); Serial.print(activeTracks[0]); Serial.print(F(", ")); Serial.print(activeTracks[1]); Serial.print(F(", ")); Serial.println(activeTracks[2]); } return;
}
// PLAYING: check 9 guess buttons
for (uint8_t i=0; i<9; i++) {
if (buttonPressed(GUESS_BTN_PINS[i], lastReadMsGuess[i])) {
uint8_t guessedTrack = i + 1; // button i corresponds to track i+1
int idx = findActiveIndexForTrack(guessedTrack);
if (idx >= 0 && !solved[idx]) {
// Correct: fade out that track
fadeOutCorrect(guessedTrack);
solved[idx] = true;
Serial.print(F("Correct: track ")); Serial.println(guessedTrack);
} else {
// Wrong guess: do nothing (no penalty), or play an error SFX if desired
Serial.print(F("Not active: track ")); Serial.println(guessedTrack);
}
}
}// If all three guessed → reset
if (allSolved()) {
// Small delay so the last fade can finish
static unsigned long allSolvedAt = 0;
if (allSolvedAt == 0) {
allSolvedAt = millis();
}
// wait slightly longer than fade time
if (millis() - allSolvedAt > (CORRECT_FADE_MS + 200)) {
resetGameAudio();
gameState = IDLE;
allSolvedAt = 0;
Serial.println(F(“Round complete. Press START for next round.”));
}
}
}
I’ll start from here and see where it takes me.