Forum

One button and random sounds

More
#582 by ericleven
ericleven created the topic: One button and random sounds
I've seen dozens of toys that do this but I can't figure out how to get Foxonix to do it:

I'd like to have one button and n number of sound files. Each button press should randomly select a sound and play it. Is there a snippet of code to help me with this? Bonus would be code that prevents the same sound from being played twice in a row.

Thanks for any help!

Eric

Please Log in or Create an account to join the conversation.

More
#583 by foxonix
foxonix replied the topic: One button and random sounds
Hi Eric:

The rand command will be described in the next batch of commands that we put up on the site, but you can find hints of how to use it already. Here's how it works.

First you need to define a [random] section in your program as shown on the Program Structure page. You have two random variables at your disposal, rand0 and rand1. In the [random] section define which variable(s) you are using and what the maximum random number should be. So if you wanted to use rand0 to generate a number between 0 and 3, you would put this in your code:
[random]
rand0=3

Then, in the [paths] section of your code, where you want to make a selection based on the random variable, you would use this code:
& rand0:[label0 label1 label2 label3]
What this means is:
If rand0 = 0, then jump to label0:
If rand0 = 1, then jump to label1:
If rand0 = 2, then jump to label2:
If rand0 = 3, then jump to label3:

If you want to guarantee that the same label isn't called twice in a row, you would need to do that check when you call the label. That is, you'd have to store the last random number in a register (like M0) and then compare the new random number with the last random number. If they're the same, then jump back to the line where the number is generated and the label is called.

Another way to achieve this same result without using a random variable is to use a pseudo-random sequence that you establish yourself. This way you can guarantee that the same label isn't called twice in a row. For example, you could have code that looks like this:
play_phrase:
	& M0=M0+1
	& M0:[label1 label3 label2 label0 label1 lablel2 label3 label0] M0=0 play_phrase
Each time play_phrase is called, M0 will increment to point to the next element in the array. The elements in the array are arranged so that they appear random. If M0 increments to the point where it is larger than the maximum number of elements in the array, then M0 is set to 0 and the program jumps back to the play_phrase label. Your sequence of labels can be make longer to make the arrangement seem even more random. If you use an M register to call the array, then you can include up to 16 elements in the array. If you use an X register to call the array, then you can include up to 256 elements in the array.

More information on registers can be found in the Data Format section on the Programming Reference page.

Foxonix - make your ideas heard.
@foxonixdev
The following user(s) said Thank You: ericleven

Please Log in or Create an account to join the conversation.

More
#604 by ericleven
ericleven replied the topic: One button and random sounds
Hi Will,

I'm generating a random number and checking it against a register to make sure the same sound isn't played twice in a row. But if my random number is the same as last time, I'm not sure how to generate a new random number:

For example, I set a random number in the [random] section:
rand0=1

which is generating a new random number...somewhere?...between button presses. I tried to make a new path that would force a new random number, but I'm getting a syntax error, so I know that's not right.
newRandomNumber:
	& rand0=1
	& button

The idea is if the current random number is equal to the last random number (stored in M1), make a new random number.
button:
	& rand0?M1:newRandomNumber
	& rand0:[play1 play2]
	& end			; stop the program and enter low power mode

play1:
	& one.wav
	& M1=0
	& end

play2:
	& two.wav
	& M1=1
	& end

In theory, I should be getting "1", "2", "1", "2", and so on with each button press. What am I missing?

Thanks in advance!

Please Log in or Create an account to join the conversation.

More
#605 by foxonix
foxonix replied the topic: One button and random sounds
Hi Eric:

So close! Most of your code is right, there's just a misunderstanding with how the rand variable is used.

The code
rand0=1
only needs to be done once in the [random] section of the program. This tells the compiler that you'll be using random variable rand0 and that you want to generate numbers from 0 to 1. After that, the random number is generated when you use the variable. So when you execute the code
rand0:[play1 play2]
that's when the new random number is generated and play1 or play2 is called based on the random number. To guarantee that the same path is not called twice in a row, you can generate a random number and store it (in M2 for example). Then you can compare the value in M2 with the value in M1 (which was set from last time you called a path). If they're the same, then jump back to button: and get a new random number. If they're not the same, then M2 (which holds the new random number) is used to select the path. The code provided below was tested and works.

button:
  & delay(0.020)     ; small delay to guarantee a new random number is generated
  & M2=rand0         ; get a random number and store in M2
  & M2?M1:button     ; compare new and last random number. If same, jump back to button:
  & M2:[play1 play2] ; otherwise, jump to label based on new random number

play1:
  & one.wav
  & M1=0
  & end

play2:
  & two.wav
  & M1=1
  & end

Note that there is a short delay statement before the rand0: call. This may seem extraneous (and is from a program function point of view) but it's necessary to guarantee that a new random number is generated. Without it, the chip keeps generating the same number (not random). Give the code a try and see how it works for you.

Foxonix - make your ideas heard.
@foxonixdev

Please Log in or Create an account to join the conversation.

More
#606 by ericleven
ericleven replied the topic: One button and random sounds
Ok! I used your code and it worked great. I started to put my actual project together and I'm running into some trouble: my actual project has 63 sound files.

First problem: rand0 looks like it's only a 4 bit number, so I can't do rand0=62. I figured I'd generate 0-15 in rand0 and 1-5 in rand1 and multiply them together to get 0-75 (I'm not quite sure how I'll get 0-75 remapped to 0-62, but I'll worry about that for my second problem).

I tried this:
button:
	& delay(.02)     ; small delay to guarantee a new random number is generated
	& M0=rand0       ; get a random number from 0-15
	& M1=rand1       ; get another random number from 0-4
	& M1=M1+1        ; move second random number from 0-4 to 1-5
	& X1=M0*M1       ; mult first and second random numbers together to get 0-70
	& X2?X1:button   ;make sure we don't play the same sound twice
	& X2:[play1 play2 play3 play4 play5 ... play62]
	& end			; stop the program and enter low power mode

It looks like it doesn't like my multiplication. Does the scripting language allow multiplication or division?
I'm hoping the answer here is some fancy binary math rather than "Why in the world do you have so many sounds?"

Followup question: Does EZscript have any kind of compare operators, so I can say
if (X1 > 61) generate another random number
?

Thanks!

Please Log in or Create an account to join the conversation.

More
- #607 by foxonix
foxonix replied the topic: One button and random sounds
Hi Eric:

You can't multiply two numbers together, but (as you suggested) you can do it with two different random variables. If you're trying to call 63 different paths, you could set rand0=8 (generates 9 different numbers) and rand1=6 (generates 7 different numbers), for a total of 63 combinations. You then need to make two different jumps based on the variables. The code would look something like this:

; use the first random variable to randomly select one of nine arrays
  & rand0:[array0 array1 array2 array3 array4 array5 array6 array7 array8 ]

; then use the second random variable to randomly call one of seven paths
array0:
  & rand1:[path0 path1 path2 path3 path4 path5 path6 ]

array1:
  & rand1:[path7 path8 path9 path10 path11 path12 path13 ]

; ... and so on until all nine arrays and all 63 paths are accounted for

So while it's not a direct call to one of 63 paths, this turns out to be a neat and orderly way to arrange your code, which is always nice. You can have up to a total of 256 different sound files, so 63 is totally reasonable!

Yes, there are operators for greater than and less than, and they are described here in the reference section . These operators work for 8-bit values (X registers), but since you're comparing random variables (which top out at 15) you'd probably have to do two different compares using 4-bit (M) registers. However, if you stick with 63 sound files then you may not need to do any comparing at all, since you're generating the exact number of random possibilities you need.

Foxonix - make your ideas heard.
@foxonixdev
Last Edit: by foxonix. Reason: Added extra text
The following user(s) said Thank You: ericleven

Please Log in or Create an account to join the conversation.

Time to create page: 0.024 seconds