wekinator

Hannah Kim
4 min readFeb 22, 2024

Wekinator #3

In our quietest moments, our gaze often drifts to the distance, lost in thought. Imagine a system that understands the depth of your contemplation. This wekinator notices whether or not you make a “pensive” gaze, playing a song that complements your state of mind. This wekinator surprised me at how well it can classify “pensive” over all the other facial expressions/movements.

SndBuf song1 => dac;
SndBuf song2 => dac;

"pensive.wav" => song1.read;

0 => song1.pos;
1 => song1.rate;

// Initially stop both songs
0 => song1.gain;

// Create our OSC receiver
OscIn oin;
// Create our OSC message
OscMsg msg;
12000 => oin.port;

oin.addAddress("/wek/outputs");
// Print
cherr <= "listening for \"/wek/outputs\" messages on port " <= oin.port() <= "..." <= IO.newline();

while(true)
{
oin => now;

// Grab the next message from the queue
while(oin.recv(msg))
{
for(int i; i < msg.numArgs(); i++)
{
float current;
msg.getFloat(i) => current;
// Play song1 if the message is 1
if(current == 1)
{
// Play song1
1 => song1.gain;
cherr <= "super pensive" <= IO.newline();
}
else {
cherr <= "..." <= IO.newline();
0 => song1.gain;
}
}
}
}

Wekinator #2

Here, I can change the pitch and volume of the song “Cupid” based on my upper face and mouth movement. I was trying my best to avoid any smolder-based classification, but FaceOSC can tell the difference in eye and mouth position the best. I envision DJs using this tool, and instead of fidgeting around with their motherboards, they can use their faces for free! FaceOSC is super finicky, so I did have a bit of a learning curve trying to control this wekinator and figure out which facial expressions work best.

SndBuf2 mySound => dac;  
"speed-up.wav" => mySound.read;
1 => mySound.loop;

// OSC setup
OscIn oin;
12000 => oin.port;
oin.addAddress("/wek/outputs");
<<< "listening for \"/wek/outputs\" messages on port", oin.port(), "..." >>>;
OscMsg msg;
//pitch and volume control
0.0 => float pitchShift;
1.0 => float volumeLevel;

// Infinite event loop
while(true) {
oin => now;

while(oin.recv(msg)) {
if(msg.numArgs() >= 2) {
// Get pitch shift value (assuming it's sent as a float)
msg.getFloat(0) => pitchShift;
// Get volume level
msg.getFloat(1) => volumeLevel;

pitchShift => mySound.rate; // Adjust playback rate for pitch shifting
volumeLevel => mySound.gain; // Adjust gain for volume control

// Debug
<<< "Pitch Shift:", pitchShift, "Volume Level:", volumeLevel >>>;
}
}
}

Wekinator #1

Sometimes, life hands us a big, fat serving of meh. You know the feeling — when even the thought of doing something productive makes you want to take a 6-hour nap. But then, there are moments when the universe decides you’ve had enough and gives you a glimmer of hope… in the form of cat photos and random compliments. Because, let’s face it, nothing says “chin up, buddy” quite like a fluffy kitten or being told you’re the human equivalent of a double rainbow.

So, why not take it up a notch? Imagine your computer turning into your personal cheerleader. It watches you. All the time. But it’s for a noble cause — classifying your every frown, eye roll, and sigh of existential dread to bombard you with happy websites. Picture it: You’re about to spiral into the depression, and bam! Your screen floods with puppies, memes, and a screen that says, “Your hair looks great today.” Why not let technology throw you a lifeline of absurdity? So, here’s to letting our devices peer into our souls (or just our facial expressions) to save us from dejection. Because sometimes, we don’t need solutions; we just need distractions.

Previous experiments include:

  • flashing different colors based on moods
  • playing different music based on moods
import oscP5.*;
import netP5.*;
import ddf.minim.*;
import java.awt.Desktop;
import java.net.URI;

OscP5 oscP5;
NetAddress myRemoteLocation;
float current;
long lastCheck = 0;
int interval = 500; // Check interval set to 500 milliseconds for demonstration

Minim minim;
AudioPlayer player;

// List of links to randomly choose from
String[] links = {
"https://reasonstobecheerful.world/",
"https://emergencycompliment.com/#",
"https://www.dailypuppy.com/",
"https://thenicestplace.net/",
"https://www.nytimes.com/games/wordle/index.html",
"https://dontevenreply.com/",
"https://explore.org/livecams/cats/kitten-rescue-cam"
};

String sadMusicPath = "speed-up.wav";

void setup() {
size(400, 200);
oscP5 = new OscP5(this, 12000); // Listening on port 12000
println("Listening for \"/wek/outputs\" messages on port 12000...");

minim = new Minim(this);
player = minim.loadFile(sadMusicPath, 2048); // Load the sad music file
}

void draw() {
background(200);
if (millis() - lastCheck > interval) {
lastCheck = millis();
}
}

void oscEvent(OscMessage msg) {
if (millis() - lastCheck < interval) return; // Ignore if within quiet period

if (msg.checkAddrPattern("/wek/outputs")) {
for (int i = 0; i < msg.typetag().length(); i++) {
current = msg.get(i).floatValue();
if (current == 1) {
println("YAY! I'm so glad you're happy");
if (player.isPlaying()) { // Stop music if it's playing when happy
player.pause();
player.rewind();
}
} else if (current == 2) {
println("shit, you're sad.");
if (!player.isPlaying()) { // Play music only if it's not already playing
player.play();
}
// Randomly choose a link from the list when sad
int index = (int) random(links.length);
openWebpage(links[index]);
}
}
}
}

void openWebpage(String url) {
try {
if (Desktop.isDesktopSupported()) {
Desktop.getDesktop().browse(new URI(url));
}
} catch (Exception e) {
e.printStackTrace();
}
}

void stop() {
player.close(); /
minim.stop();
super.stop();
}

--

--