0

I've got that bit of code (see below) which randomly selects between letters A through to X. I created few characters empty space after each letter in string because I'm not sure how to do that otherwise, maybe some of you knows how to fix that as well? That would surely make the code look a bit more condense and neat.

At the moment every time each of these letters gets selected one sound is being played (click_001.wav).

I want to diversify it, so when it selects letters from A to P, it plays "click_001.wav", and when from Q to X, it plays "mouse_click.wav".

I know the code won't work for you fully since you haven't got the wave file so in the link below I prepared the files ready to download if needed. I'm using "processing.sound" library in this example as well which can be added to processing via menu in processing: Sketch > Import library > Add Library > in the search bar type: sound. It's the sound library from The Processing Foundation.

https://www.dropbox.com/sh/madgao8vhjum6yz/AADJsNWQAvcyIaP8aVjWN6-Sa?dl=0

Could any of you help me with that, please?

Best regards,
Still human being

String[] words = {"A  ", "B  ", "C  ", "D  ", "E  ", "F  ", "G  ", "H  ", "I  ", "J  ", "L  ", "M  ", "N  ", "O  ", "P  ", "Q  ", "R  ", "S  ", "T  ", "U  ", "V  ", "W  ", "X  "};
int newIndex = 0;
int oldIndex = -1;
PFont SansSerif;
String beat = "";
int x = 0;
import processing.sound.*;
SoundFile file;

void setup() {
  size(950, 600);
  SansSerif = createFont("SansSerif", 150);
  textFont(SansSerif);
}

void draw() {
  frameRate(.6); 
  background(35); 
  // Get a random element from array
  newIndex = int(random(words.length));  
  if (oldIndex > -1) {
     file = new SoundFile(this, "click_001.wav");
     file.play();
    beat = words[oldIndex] + words[newIndex];
    int x = 250;
    for (int i = 0; i < beat.length(); i++){
      if(i == 0){
        
        fill(250);
      } else {
      
        fill(50);
      }
      text(beat.charAt(i), x, 350);
      x += 65;
    }
    println("old =", words[oldIndex] + " : " +  "new =", words[newIndex] ); 
  } else {
    fill(250);
    text(words[newIndex],  250, 350);
    println("new =", words[newIndex]);
  }
  oldIndex = newIndex;
}

1 Answers1

0

You can drop the spaces in the 'words' array by just setting the x coordinate for each text call instead of using a variable. I added the letter 'K' which you apparently left out. Also added was a new function to play a sound for each character in the beat string. The two sound files need to be placed in a folder titled 'data' in the sketch folder.


String[] words = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X"};

int newIndex = 0;
int oldIndex = -1;
PFont SansSerif;
String beat = "";

import processing.sound.*;
SoundFile file;

void setup() {
  size(800, 600);
  SansSerif = createFont("SansSerif", 150);
  textFont(SansSerif);
}

void playSoundForChar(char inChar) {
  if ((inChar=='Q')||(inChar=='R')||(inChar=='S')||(inChar=='T')||(inChar=='U')||(inChar=='V')||(inChar=='W')||(inChar=='X')||(inChar=='Y')||(inChar=='Z')) {
    file = new SoundFile(this, "mouse_click.wav");
    println("click2", inChar);
  } else {
    file = new SoundFile(this, "click_001.wav");
    println("click1", inChar);
  }
  file.play();
}

void draw() {
  // frameRate(.6);
  frameRate(1);
  background(35);
  // Get a random element from array
  newIndex = int(random(words.length));
  if (oldIndex > -1) {
    beat = words[oldIndex] + words[newIndex];
    println("old =", words[oldIndex] + " : " +  "new =", words[newIndex] );
    for (int i = 0; i < beat.length(); i++) {
      if (i == 0) {
        fill(250);
        text(beat.charAt(i), 250, 350);
        playSoundForChar(beat.charAt(i));
      } else {
        fill(50);
        text(beat.charAt(i), 450, 350);
        playSoundForChar(beat.charAt(i));
      }
    }
  } else {
    beat = words[newIndex];
    println("new =", words[newIndex]);
    for (int i = 0; i < beat.length(); i++) {
      if (i == 0) {
        fill(250);
        text(beat.charAt(i), 250, 350);
        playSoundForChar(beat.charAt(i));
      }
    }
  }
  oldIndex = newIndex;
}

This revision of function playSoundForChar() demonstrates changing the rate and pitch of each sound. It should allow the two sounds to be more clearly distinguished. The console 'println' record of which sound was played should be accurate.

import processing.sound.*;
SoundFile file;

String[] words = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X"};
int newIndex = 0;
int oldIndex = -1;
PFont SansSerif;
String beat = "";

void setup() {
  size(800, 600);
  SansSerif = createFont("SansSerif", 150);
  textFont(SansSerif);
}

void playSoundForChar(char inChar) {
  if ((inChar=='Q')||(inChar=='R')||(inChar=='S')||(inChar=='T')||(inChar=='U')||(inChar=='V')||(inChar=='W')||(inChar=='X')||(inChar=='Y')||(inChar=='Z')) {
    file = new SoundFile(this, "4clicks.mp3");
    println("click2", inChar);
    file.play(2); // plays it twice as fast, one octave up
  } else {
    file = new SoundFile(this, "3clicks.mp3");
    println("click1", inChar);
    file.play(0.5); // plays it half as fast, one octave down
  }
}

void draw() {
  frameRate(.6);
  background(35);
  // Get a random element from array
  newIndex = int(random(words.length));
  if (oldIndex > -1) {
    beat = words[oldIndex] + words[newIndex];
    println("old =", words[oldIndex] + " : " +  "new =", words[newIndex] );
    for (int i = 0; i < beat.length(); i++) {
      if (i == 0) {
        fill(250);
        text(beat.charAt(i), 250, 350);
        playSoundForChar(beat.charAt(i));
      } else {
        fill(50);
        text(beat.charAt(i), 450, 350);
        playSoundForChar(beat.charAt(i));
      }
    }
  } else {
    beat = words[newIndex];
    println("new =", words[newIndex]);
    for (int i = 0; i < beat.length(); i++) {
      if (i == 0) {
        fill(250);
        text(beat.charAt(i), 250, 350);
        playSoundForChar(beat.charAt(i));
      }
    }
  }
  oldIndex = newIndex;
}
apodidae
  • 1,988
  • 2
  • 5
  • 9
  • Thanks a lot for your help! I'm getting an error while playing the metronome now though. This part gets highlighted in yellow: "file.play();" and in the bottom window I get red notification: "NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException Could not run the sketch (Target VM failed to initialize). For more information, read revisions.txt and Help ? Troubleshooting. " – still_human_being Jan 08 '22 at 16:40
  • Did you place the two sound files in a folder called 'data' inside of the sketch folder? – apodidae Jan 08 '22 at 16:45
  • I actually forgot to do that. Now when I do it, the whole thing doesn't play at all. I found though that when the audio files are in the same folder as the processing file, it plays them but sometimes plays them both at once, which is not quite the aim yet. I updated the files I am now using in the dropbox folder. – still_human_being Jan 08 '22 at 18:28
  • You have to create a folder inside of your sketch folder and call it 'data'. The sound files go inside there. Which file goes with which group? It would help to shorten the names. – apodidae Jan 08 '22 at 18:39
  • Ok, I placed the "data" folder in the wrong place. Now it works but something is wrong with the playback. The file 4clicks should go with letter from A to P, and 3 clicks from Q to X. They seem to be overlapping at the moment so it goes work. The audio files are adjusted to the frameRate(.6). I shortened the name files and updated in dropbox. – still_human_being Jan 08 '22 at 20:01
  • The audio files seem to be played both at once at certain letters, both from group that counts in 4 as well as in 3. As if the randomness applies to it as well. (in a way) – still_human_being Jan 08 '22 at 20:09
  • . All you have to do is reverse the order in the function 'playSoundForChar()' if they are not in the correct order. I doubt that they 'overlap'; both sounds contain a bunch of 'clicks' and they are played back to back as far as I know. I agree that it sounds strange but that's not necessarily the code's fault. But then I'm not a drummer ;-) – apodidae Jan 08 '22 at 20:12
  • They do overlap, trust me :) I changed and simplified the sound a bit so it's easier to distinguish one from another now (shortened the names even more as well). So now 4 plays even 4 woodblock sounds, and 3 plays 3 weird electronic sounds. See if that makes it a bit clearer to hear, if not no worries. I think this might something to do with the sound engine specifically. Thanks for all your help with this anyway! – still_human_being Jan 08 '22 at 20:35
  • 4clicks+3clicks = 7clicks; they all sound the same to me. How on earth would you know if they were overlapped? Most metronomes that I have experience with play one sound per beat. Are 'drummer' metronomes different? – apodidae Jan 08 '22 at 20:42
  • Maybe they simply sound better on your computer than on mine? I have an idea what could be causing the issue. I think the way it works, the sound is being played everytime each letter on both right and left hand side, appears. Is this the case? Is so, would you be able to make just the letter on the left hand side play a sound? I am happy to create new thread/ question. – still_human_being Jan 08 '22 at 22:20
  • See recent edit. A sound is played every time a letter is added. I changed the rate of each (one up, one down) which also affects the pitch so that the two may be more easily distinguished. I have no problem with another thread. If you're only going to play a sound for the left hand letter, what's the purpose of a second letter on the right? I've written several metronome demos and have always used colored discs for 1&, 2&, 3&, 4& etc. with different colors for the down beat and up beat. Sometimes I have also put the beat no. on the disc. – apodidae Jan 08 '22 at 22:31
  • The reason for the letter on the right hand side to be not played is that I just need it there so I know what the next letter will be. So the idea is that I hear only one letter at a time (the one on the left). Slowing or speeding the sound files isn't what I'm after. This particular metronome is slightly different to anything else I have seen so far. I think it's because it's based on that document: https://bennygrebshop.bigcartel.com/product/the-language-of-drumming-poster – still_human_being Jan 08 '22 at 22:53
  • Letters A to P are based on quarter note pattern and from Q to X on a triplet note pattern. So depending on which letter we have, there are either 3 or 4 sound falling between the showing letters, in the same space of time (tempo). – still_human_being Jan 08 '22 at 22:53
  • My interpretation of the Benny Greb exercise is a little different from yours. To me the top (A-P) represents 16 bars of a timing exercise in 4/4 time. The circles are played 'notes' (eg hand claps or finger snaps) and the dashes are not played. It is meant to help the student internalize musical timing; ie create their own internal metronome which every good musician has to have in order to play on beat. The bottom of the page (Q-X) appears to be in 3/4 time (3 beats per measure) and has nothing to do with triplets. – apodidae Jan 09 '22 at 07:10
  • yeah, but that's beside the point. are you able to make only the letter on the left trigger the sound? – still_human_being Jan 09 '22 at 10:05
  • You should be able to figure out how to silence the right letter by looking at the code. There's only two letters, the one on the left has an x coordinate of 250 and the one on the right has an x coordinate of 450. Look in the draw() and remark out (insert // in front of) the function playSoundForChar() which appears immediately after the text() call with a 450 x coordinate. – apodidae Jan 09 '22 at 14:59
  • Thanks a lot! It works now. You are right about the triplets. I'm still learning the whole music theory. – still_human_being Jan 09 '22 at 15:22