14 March 2021

NIME Video Game Music Box




My NIME project is a music box that lets you alter and play the beginning of the Tetris theme and Megalovania. The conceptual model was a device that allows you to alter a note or song, incrementally, using the potentiometer.

The box has 4 inputs which utilize the speaker as an output. The right button plays the beginning of the Tetris theme when the device is up-right. The left button plays a repeating note as long as it is held. This repeating note(b) is primarily intended to indicate the effects of the potentiometer, as it adjusts two functions simultaneously. First, it multiplies the frequencies of the base notes. This has four stages, from 1x to 4x, with each stage raising the octave. Secondly, it shortens the length in which each note is played, effectively changing the tempo. This is done, in 4 stages, by dividing the base notes length (x/1, x/2 , x/3, x/4). The accelerometer was utilized to create a bit of an easter egg. The box will play Megalovania when it is placed on it’s side and the right button is pressed. This song is also affected by the octave/tempo setting. Additionally, the songs played with the right button output to the servo. The servo has a plastic arm that flicks a small aluminum sheet as it moves. The servo oscillates each time it is called to create a percussive noise that is used as a drum beat.


Excluding the, intentionally secret, function I wanted to make everything easy to understand, so my main question is: Is the device’s function communicated well via it’s current feedback and design, and do you suggest any changes on that front?


Schematic:

Code:
/* * NIME * Tetris Music Box - Cameron Friday */ #include <Servo.h> #include <Adafruit_CircuitPlayground.h> #include <Adafruit_Circuit_Playground.h> //for servo Servo myServo; int pos = 0; //Starting position int drum = 0; //Current state (0,1) //for potentiometer int potPin = A2; int potValue; int mappedTone; //Frequency modifier int mappedRate; //Tempo modifier void setup() { Serial.begin(9600); delay(1000); CircuitPlayground.begin(); myServo.attach(10); //Servo Pin pinMode(CPLAY_LEFTBUTTON, INPUT_PULLDOWN); pinMode(CPLAY_RIGHTBUTTON, INPUT_PULLDOWN); analogWrite (A0, 200); //set base volume lower, as default is a bit loud. beat(); //initial servo trigger so position begins tracking } void loop() { potValue = analogRead(potPin); //read potentiometer mappedTone = map(potValue, 0, 1023, 1, 5); //map potentiometer to desired frequency in octaves mappedRate = map(potValue, 0, 1023, 1, 5); //map potentiometer to 4 stage tempo float x = CircuitPlayground.motionX(); //read accelerometer x int r = map(x,-10, 10, 0, 3); //map accelerometer to lower values, only need 2 states Serial.print("x = "); Serial.print(r); Serial.print("\t poten = "); Serial.print(potValue); Serial.print("\t tone output = "); Serial.print(mappedTone); Serial.print("\t rate output = "); Serial.println(mappedRate); //repeating tone, to sample the octave and tempo if(digitalRead(CPLAY_LEFTBUTTON) == 1) { CircuitPlayground.playTone((247*mappedTone), (100/mappedRate)); } //Tetris Theme, if up-right if((digitalRead(CPLAY_RIGHTBUTTON) == 1) && (r == 1)) { beat(); CircuitPlayground.playTone((330*mappedTone), (400/mappedRate));//e4 CircuitPlayground.playTone((247*mappedTone), (200/mappedRate));//b3 CircuitPlayground.playTone((262*mappedTone), (200/mappedRate));//c4 CircuitPlayground.playTone((294*mappedTone), (200/mappedRate));//d4 CircuitPlayground.playTone((330*mappedTone), (100/mappedRate));//e4 CircuitPlayground.playTone((294*mappedTone), (100/mappedRate));//d4 CircuitPlayground.playTone((262*mappedTone), (200/mappedRate));//c4 CircuitPlayground.playTone((247*mappedTone), (200/mappedRate));//b3 beat(); CircuitPlayground.playTone((220*mappedTone), (400/mappedRate));//a3 CircuitPlayground.playTone((220*mappedTone), (200/mappedRate));//a3 CircuitPlayground.playTone((262*mappedTone), (200/mappedRate));//c4 CircuitPlayground.playTone((330*mappedTone), (400/mappedRate));//e4 CircuitPlayground.playTone((294*mappedTone), (200/mappedRate));//d4 CircuitPlayground.playTone((262*mappedTone), (200/mappedRate));//c4 beat(); CircuitPlayground.playTone((247*mappedTone), (400/mappedRate));//b3 CircuitPlayground.playTone((247*mappedTone), (100/mappedRate));//b3 CircuitPlayground.playTone((247*mappedTone), (100/mappedRate));//b3 CircuitPlayground.playTone((262*mappedTone), (200/mappedRate));//c4 CircuitPlayground.playTone((294*mappedTone), (400/mappedRate));//d4 CircuitPlayground.playTone((330*mappedTone), (400/mappedRate));//e4 beat(); CircuitPlayground.playTone((262*mappedTone), (400/mappedRate));//c4 CircuitPlayground.playTone((220*mappedTone), (400/mappedRate));//a3 CircuitPlayground.playTone((220*mappedTone), (400/mappedRate));//a3 } //Megalovania, if device is on side if((digitalRead(CPLAY_RIGHTBUTTON) == 1) && (r != 1)) { beat(); CircuitPlayground.playTone((147*mappedTone), (100/mappedRate));//d3 CircuitPlayground.playTone((147*mappedTone), (100/mappedRate));//d3 CircuitPlayground.playTone((294*mappedTone), (200/mappedRate));//d4 CircuitPlayground.playTone((220*mappedTone), (300/mappedRate));//a3 CircuitPlayground.playTone((208*mappedTone), (200/mappedRate));//gs3 CircuitPlayground.playTone((196*mappedTone), (200/mappedRate));//g3 CircuitPlayground.playTone((175*mappedTone), (200/mappedRate));//f3 CircuitPlayground.playTone((147*mappedTone), (100/mappedRate));//d3 CircuitPlayground.playTone((175*mappedTone), (100/mappedRate));//f3 CircuitPlayground.playTone((196*mappedTone), (200/mappedRate));//g3 } } //servo 'drum' void beat(){ if (drum == 0) { pos += 70; myServo.write(pos); } if (drum == 1) { pos -= 70; myServo.write(pos); } if (pos == 70) drum = 1; if (pos == 0) drum = 0; }

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.