The concept for my the project is to visualize music and create interaction through performance. My inspiration came from the Dj Deadmaus who wears a masked disguise. The reason inspired me is because instead of doing a regular light display, I would like to make something wearable that the user can actually put on. My initial theme for mask was to make it African because it hails from my heritage. The mask is going to have inbuilt LED neopixels that react to the amplitude of the music and create a display. I will show the steps of my project using a series of pictures and videos.
I split the project into two sections, first starting with the code and then fabrication. This is the Arduino code I used at the beginning followed by processing code. Both were library examples.
This example code is in the public domain.
*/
#include "SerialRecord.h"
#include <FastLED.h>
#define TEMPERATURE_1 MercuryVapor
// How many leds in your strip?
#define NUM_LEDS 60
// For led chips like WS2812, which have a data line, ground, and power, you just
// need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
// Clock pin only needed for SPI based chipsets when not using hardware SPI
#define DATA_PIN 3
#define CLOCK_PIN 13
#define BRIGHTNESS 50
// Define the array of leds
CRGB leds[NUM_LEDS];
// Change this number to the number of values you want to receive
SerialRecord reader(1);
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const long interval = 100; // interval
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(9, OUTPUT);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
}
void loop() {
reader.read();
if (reader[0] < 20) {
// digitalWrite(LED_BUILTIN, HIGH);
// Serial.println(reader[0]);
rain_bow();
} else {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
for(int i=0; i<NUM_LEDS; i++){ leds[i] = CRGB::Blue;}
} else {
ledState = LOW;
for(int i=0; i<NUM_LEDS; i++){ leds[i] = CRGB::Orange;}
}
// set the LED with the ledState of the variable:
digitalWrite(13, ledState);
}
// memset8(leds, 0, NUM_LEDS * sizeof(CRGB)); // blinking effect!!!!!!!
FastLED.show();
// delay(500);
// celebration3();
}
delay(2);
// tone(9, reader[1]);
}
void rain_bow() {
// draw a generic, no-name rainbow
static uint8_t starthue = 0;
Serial.println("rain_bow");
fill_rainbow(leds + 1, NUM_LEDS - 2, --starthue, 30); // (start_index, end_index, starthue, deltahue)
//fill_rainbow( leds + 1, NUM_LEDS - 2, --starthue, 100); // random(start_index, end_index, starthue, deltahue)
FastLED.setTemperature(TEMPERATURE_1); // first temperature
leds[0] = TEMPERATURE_1; // show indicator pixel
FastLED.show();
FastLED.delay(0);
}
void celebration3() {
// draw a generic, no-name rainbow
static uint8_t starthue = 0;
fill_rainbow( leds + 2, NUM_LEDS - 3, --starthue, 100); // (start_index, end_index, starthue, deltahue)
Serial.println("celebration3");
FastLED.setTemperature( TEMPERATURE_1 ); // second temperature
leds[0] = TEMPERATURE_1; // show indicator pixel
FastLED.show();
FastLED.delay(100);
memset8( leds, 0, NUM_LEDS * sizeof(CRGB)); // blinking effect!!!!!!!
FastLED.show();
FastLED.delay(500);
}
/**
* Grab audio from the microphone input and draw a circle whose size
* is determined by how loud the audio input is.
*/
import processing.sound.*;
AudioIn input;
Amplitude loudness;
import processing.serial.*;
import osteele.processing.SerialRecord.*;
Serial serialPort;
SerialRecord serialRecord;
void setup() {
size(640, 360);
// String serialPortName = SerialUtils.findArduinoPort();
serialPort = new Serial(this, "COM9", 9600);
// In order to send a different number of values, modify the number `2` on the
// next line to the number values to send. In this case, the corresponding
// number in the Arduino sketch should be modified as well.
serialRecord = new SerialRecord(this, serialPort, 1 ); //------------------------------------------------------------------
// serialRecord.logToCanvas(false);
background(255);
// Create an Audio input and grab the 1st channel
input = new AudioIn(this, 0);
//// Begin capturing the audio input
input.start();
// start() activates audio capture so that you can use it as
// the input to live sound analysis, but it does NOT cause the
// captured audio to be played back to you. if you also want the
// microphone input to be played back to you, call
// input.play();
// instead (be careful with your speaker volume, you might produce
// painful audio feedback. best to first try it out wearing headphones!)
// Create a new Amplitude analyzer
loudness = new Amplitude(this);
// Patch the input to the volume analyzer
loudness.input(input);
}
void draw() {
// Adjust the volume of the audio input based on mouse position
float inputLevel = map(mouseY, 0, height, 1.0, 0.0);
input.amp(inputLevel);
// loudness.analyze() return a value between 0 and 1. To adjust
// the scaling and mapping of an ellipse we scale from 0 to 0.5
float volume = loudness.analyze();
int size = int(map(volume, 0, 0.5, 1, 350));
//println(size);
background(125, 255, 125);
noStroke();
fill(255, 0, 150);
// We draw a circle whose size is coupled to the audio analysis
ellipse(width/2, height/2, size, size);
serialRecord.values[0] = int(size);
////serialRecord.values[1] = int(map(mouseY, 0, height - 1, 0, 1023));
if (frameCount % 10 == 0) serialRecord.send();
}
void keyPressed(){
if (key == 'b'){
serialRecord.values[0] = 55;
//serialRecord.values[1] = int(map(mouseY, 0, height - 1, 0, 1023));
}
if (key == 'r'){
serialRecord.values[0] = 1;
//serialRecord.values[1] = int(map(mouseY, 0, height - 1, 0, 1023));
}
}
This is the improved code as you can see it responds with a different light pattern when I click
Fabrication process. Editing the 3d mask in blender to make it more ergonomic
After editing I started the 3d printing process, it was a 14 hour print.
Completed print, I painted over it to give it the texture of wood. I also added an elastic strap so it is easy to wear.
I House the LED’s into the mask and I had to individually solder each wire to make it work. You can observe the process below. I also applied a film over the lights to hide them, therefore making it more aesthetic.
Testing with music
For user testing I got a lot of useful feedback. The people thought it was a fun concept and kept them entertained throughout the use but the interaction was simple and did not do enough. As an improvement I added more features such as a track list that you could change songs by tilting your head. The mask switches between modes. Mode 1 is the first one which you can observe in the previous videos. Mode 2 is being able to switch through the track list using a tilt sensor. Below is a video of the second concept. This makes the mask into more of a console the controls the music. I also played a whole set using the mask that can be viwed on this link :
This project opened my eyes to the possibilities of enhancing performance between the performer and the audience using music and light. If I had more time I would do more research on how to add even more interactive elements to make listening to music an experience and create memories.