A video went viral this week showing two AIs talking to each other, as if on the phone (see here). They start in English, but once they realize they are both AIs, they switch into an artificial "language" called Gibberlink (or more formally, GGWave). I was immediately fascinated because it sounds basically like the droids (e.g. R2-D2) from Star Wars — but this is real!
I went to the GGWave project page, and discovered that they have a web service that returns a GGWave sound file for a given message (along with some other options, like whether to use the slow or fast version). Mini Micro supports web services. So let's do this!
Make your Mini Micro talk like a droid
Fire up Mini Micro (if you don't already have it, download it here), and paste in this code at the prompt:
http.get("https://ggwave-to-file.ggerganov.com/?m=Hello%20world!").play
You should hear a bunch of bleeps and blurps that are how you say "Hello world!" in droid speak. It's so easy!
Fancy it up
But I couldn't leave it there. I wanted to wrap up that call in a handy say
function, so I could just do things like say "whatever"
and have it play the appropriate sounds. And then, to be kind to the server, I decided to cache the sounds so that if you ask it to say the same message twice, it only hits the server once. I ended up with this code:
import "stringUtil"
_cache = {} // key: url; value: sound
getGGWaveSound = function(message, protocolId)
url = "https://ggwave-to-file.ggerganov.com/?m=" +
message.urlEncode +
"&p=" + protocolId
if not _cache.hasIndex(url) then
_cache[url] = http.get(url)
end if
return _cache[url]
end function
say = function(message, fast)
if fast == null then fast = message.len > 16
if fast then protocolId = 2 else protocolId = 1
getGGWaveSound(message, protocolId).play
end function
if locals == globals then say "Hello world!"
Still pretty simple! The other feature I added was support for the two protocols (fast and slow). If you don't specify, then the say
function will speak (in Gibberlink!) fast if the message is over 16 characters, but slowly if it's shorter than that. I found this to be a pretty nice balance, letting short messages like "Hello" take their time, but switching to faster talk for longer speeches.
Still not fancy enough
Then, I felt it needed some visuals... and I thought about this post from late 2023 where I showed how to do lip-syncing in Mini Micro. What would it look like if an AI spoke in Gibberlink, but still moved its mouth as if speaking normally? I had to know!
So I cloned the code from that project, and made a few minor changes:
- I added
import "ggwave"
at the top, to bring in the code we wrote above. - In place of
file.loadSound
, I create the speech file this way:
msg = "Hello! This is the MiniScript Control Program," +
char(13) + "wishing you a very happy day."
speech = ggwave.getGGWaveSound(msg, fast)
- I also added some code to print the message as it plays, character by character, for the benefit of us poor humans who can't actually understand Gibberlink.
(Twist this open to see the complete code.)
import "ggwave"
if not globals.hasIndex("fast") then fast = false
clear
mainImage = file.loadImage("mcp.png")
gfx.drawImage mainImage, 480-mainImage.width/2, 320-mainImage.height/2
jawSprite = new Sprite
jawSprite.image = file.loadImage("mcp-jaw.png")
jawSprite.x = 541; jawSprite.y = 151
jawSprite2 = new Sprite
jawSprite2.image = jawSprite.image
jawSprite2.x = 411; jawSprite2.y = 151
display(4).sprites = [jawSprite, jawSprite2]
list.swap = function(i,j)
temp = self[i]
self[i] = self[j]
self[j] = temp
end function
c = jawSprite2.corners
c.swap(0,1); c.swap(2,3) // (flips the image horizontally)
jawSprite2.setCorners c
openMouth = function(amount)
c = jawSprite.corners
dy = 32 * amount
c[0][1] = c[1][1] - dy // bottom inner corner
c[3][1] = c[2][1] - dy // top inner corner
jawSprite.setCorners c
c = jawSprite2.corners
c[0][1] = c[1][1] - dy // bottom inner corner
c[3][1] = c[2][1] - dy // top inner corner
jawSprite2.setCorners c
end function
//speech = file.loadSound("happyNewYear.ogg")
msg = "Hello! This is the MiniScript Control Program," +
char(13) + "wishing you a very happy day."
speech = ggwave.getGGWaveSound(msg, fast)
charsPerSec = msg.len / (speech.duration - 0.5)
text.color = "#88AAAA"
startTime = time
speech.play
amount = 0
while speech.isPlaying
a = speech.amp
target = a * 5 // (found experimentally)
amount = (amount + target*4) / 5
openMouth amount
charsToShow = (time - startTime) * charsPerSec
text.row = 2
print msg[:charsToShow]
yield
end while
openMouth 0
text.row = 2
print msg
And the result is the video you see at the top of this post. You can see that I also ran the waver app on my phone, which understands Gibberlink — the message from Mini Micro appears on my phone as soon as it's done speaking.
How cool is that?!
You can now make Mini Micro speak like a droid, and transmit messages or data to any Gibberlink-savvy device within hearing distance.
I'm not sure what I'll use this for, but I'm certain my future includes robots and AIs chattering away in Gibberlink — perhaps with a trusty protocol droid to interpret for me (when I'm not near the display panel of my X-wing fighter, of course). And if I don't start seeing (er, hearing) Gibberlink easter-egg messages in indie video games, I shall be sorely disappointed.
What do you think? Have any ideas for cool uses for this new technology? Share your thoughts in the comments below!
Top comments (0)