I am a beginner looking for some guidance. I am trying to replicate this sound.
My daughter is a huge fan of this show (Supernatural) and I am trying to make a simple toy version of their EMF detector for her. I have the prop made and the lights working, but I am having trouble with the sound.
Would the tone() function be the best thing to use for this? I DO NOT want to use analog input for this like in the Pitch Follower sample http://arduino.cc/en/Tutorial/Tone2, I just want to press a button and have the sound play in a loop until the button is released so she can pretend she is "demon hunting".
I tried using the code below, but I couldn't get anything close.
/* Example 4.2
void setup()
{
pinMode(8, OUTPUT); // speker on pin 8
}
int del = 250; // for tone length
int lowrange = 2000; // the lowest frequency value to use
int highrange = 4000; // the highest...
void loop()
{
// increasing tone
for (int a = lowrange; a<=highrange; a++)
{
tone (8, a, del);
}
// decreasing tone
for (int a = highrange; a>=lowrange; a--)
{
tone (8, a, del);
}
}
I'd be happy to work with a tutorial that does something similar, or any guidance would be greatly appreciate.
Hi, even it is true that you can play any sound with my SimpleSDAudio library, but for such an simple sound like shown in the video it should be possible to generate it by a little bit of C code. I think your example is not so wrong, but play a bit more with the parameters. Instead of using tone (8, a, del); use something like tone (8, a); delayMicroseconds(1000); to adjust the tone-length manually. The next parameters are the high- and lowrange variables, try to adjust them first to get some of the same lowest and highest tone. If the tone rise/drowning is still not fast enough, try to adjust the for-loop -- instead of a++ try something like a+=3 or more for quicker variation.
All that involves some kind of trying, you have to play a little to find a nice sound. If it is not close enough to the movie and you wish the original sound you have to go with a sample-based variant. If the sound is not longer than a second you could use a sample-player library or example that embeds the sample in the source code so you don't need an SD-card, but the quality is often very limited then.
Thanks for the help. In the meantime, I have been working on the code below. It works with the LEDs and the sound. The problem is, the sound is not quite a smooth as in the video. Any suggestions? I would really appreciate the help.
//Pitch follower and sequential LED lighter
//Plays a pitch and lights LEDs based on a changing analog input
//8-ohm speaker on digital pin 9
//====constants=====//
//const int NUM_READINGS=15;//raise this number to increase data smoothing for LEDs - original number
const int NUM_READINGS=60;//raise this number to increase data smoothing for LEDs
const int SENSE_LIMIT=15;//raise this number to decrease LED sensitivity (up to 1023 max)
const int LEDS=5;
const int LED_PINS[LEDS]={2, 3, 4, 5, 6};
const int LED_THRESHOLDS[LEDS]={5, 16, 27, 38, 50};//what value the reading should be for LED i to light
const int PROBE_PIN=5;//analog input for both LEDs and pitch following
//=====global variables=====//
//variables for smoothing
int gReadings[NUM_READINGS];//the readings from the analog input
int gIndex=0;//the index of the current reading
int gTotal=0;//the running total
//=====main=====//
void setup(){
Serial.begin(9600);
for(int i=0; i<LEDS; ++i) pinMode(LED_PINS[i], OUTPUT);
for(int i=0; i<NUM_READINGS; ++i) gReadings[i]=0;
}
void loop(){
int sensorReading=analogRead(PROBE_PIN);
//-----LEDs-----//
int val=constrain(sensorReading, 1, SENSE_LIMIT);//constrain between 1 and SENSE_LIMIT
val=map(val, 1, SENSE_LIMIT, 1, 1023);//remap the constrained value to a 1 to 1023 range
gTotal-=gReadings[gIndex];//subtract the oldest reading
gReadings[gIndex]=val;
gTotal+=gReadings[gIndex];//add the new reading to the total
++gIndex;
gIndex%=NUM_READINGS;
int average=gTotal/NUM_READINGS;
for(int i=0; i<LEDS; ++i) digitalWrite(LED_PINS[i], (average>LED_THRESHOLDS[i])?HIGH:LOW);
//-----pitch following-----//
//print the sensor reading so you know its range
//Serial.println(sensorReading);
Serial.println(average);
//map the analog input range
//to the output pitch range (523 - 650Hz)
//change the minimum and maximum input numbers below
//depending on the range your sensor's giving:
//int thisPitch=map(average, 400, 1000, 120, 1500); original numbers
int thisPitch=map(average, 5, 50, 523, 650);
//play the pitch:
if(average<LED_PINS[0]) noTone(9);
else tone(9, thisPitch);
//delay(1);//delay in between reads for stability
delay(0);//delay in between reads for stability
}