---
title: 'Meowifier: A Hiss-tory Lesson'
teaser: The tail of how it all started.
tags: fun,code,ruby,api,inspiration
author: Beth Haubert
published_on: 2019-10-04
---

The worldwide sensation (and eventual flaming pile of 💩) Game of Thrones
premiered in the year of our Lord Stark 2011. If you're anything like me, you
would look forward to Sunday evenings -- settling into your sofa with your three
cats and/or significant other, waiting for the opening credits to start at 8pm
CST (I was living in Omaha, Nebraska at the time). There would be so much
excitement building up, but no way to release it and the opening credits are
soooo long. Like, one-minute-and-37-seconds long. So I released my pent-up
energy the best way I knew how -- meowing along to the melody of the Game of
Thrones theme song at the top of my lungs with my cats and/or significant other
looking on, appalled.

![nope cat](https://images.thoughtbot.com/blog-vellum-image-uploads/l3JSWSuASVKk14tHVibS_giphy.gif)

And that's how _Meowifier_ was born. And it stayed in that unrefined form for
about five years, until the year of our Lord Bolton 2016, when I was about six
months into my first software engineering job. It was the end of November,
winter was coming, and there were still 8 months until the next season of GoT
would begin. I was going through Jon Snow withdrawals and was already stuck
inside for the winter. I thought to myself, "What if I built an application
that automatically meows the Game of Thrones theme song _for_ me?" So I did,
poorly.

My goal for the core functionality was that a user could provide a song file
and _Meowifier_ would output the melody of the song sung by cats. I had a very
rough idea of how I would structure the app and the tools I would need to find
or build. The core elements of the app are a melody extractor, a meow library, a
note adjuster, and a song builder -- all written in Ruby.

## The melody extractor

Probably the most important job of my application was to be able to pull the
melody out of a polyphonic piece of music (or music with simultaneous notes,
you know, like every song you hear on the radio). Since I was still so new to
programming, I was hoping to find a tool that was also easy to use. What I found
was a tool called [SonicAPI](http://www.sonicapi.com/). It was free to use
until I hit around four hours of audio files. I ended up implementing this
method inside my SongParser class:

```ruby
# This class makes a request to an API, receives the response,
# and then creates a collection of notes.
class SongParser
  def parse
   response = HTTParty.get(sonic_api_request)
   @note_collection = response.dig("response", "melody_result", "notes", "note")
   append_array_with_note
  end
end
```

This is what a response from SonicAPI looks like (except imagine hundreds of
hashes inside the `note` array):

```ruby
{"response"=>
  {"status"=>
    {"code"=>"200"},
    "melody_result"=>
      {"notes"=>
        {"note"=>
          [
            {"midi_pitch"=>"35.9934844970703125", "onset_time"=>"0.88172335600907025821", "duration"=>"0.061564625850340136404", "volume"=>"0.029758758842945098877"},
            {"midi_pitch"=>"23.974985122680664062", "onset_time"=>"0.97460317460317458238", "duration"=>"0.24471655328798186391", "volume"=>"0.042322281748056411743"},
            {"midi_pitch"=>"35.97218704223628125", "onset_time"=>"1.2346258503401359441", "duration"=>"0.046031746031746034742", "volume"=>"0.027295669540762901306"},
            {"midi_pitch"=>"23.957599639892578125", "onset_time"=>"0.88172335600907025821", "duration"=>"0.79743764172335596108", "volume"=>"0.022882837802171707153"},
            {"midi_pitch"=>"35.9209136962890625", "onset_time"=>"0.88172335600907025821", "duration"=>"0.10743764172335601437", "volume"=>"0.0089688096195459365845"},
          ]
        }
      }
  }
}
```

## The meow library

I needed meows and I needed a lot of them. It was difficult to find an existing
collection of meows tuned to each note on a piano. _You_ try googling `cat meows
keyboard notes` and filtering through all this noise:

![keyboard cat](https://images.thoughtbot.com/blog-vellum-image-uploads/E2Dp5pNVQ26tQZyVmsIP_giphy.gif)

So I started by recording myself meowing, but only got about five notes in 
before I gave up, went back to the internet, and searched even deeper. I found
a free library of an auto-tuned man meowing. But there were only about four
octaves worth of notes, so I ended up just biting the bullet and pitch-shifting
a recording of an actual cat's meow 87 times. It took a while.

## The note adjuster

This is the part of the application that needs the most work from _me_ (as
opposed to some researcher coming up with a better melody analyzer, because that
requires some next-level skill). When I originally built this, I didn't think
too deeply about what a meow would sound like shortened or lengthened. I just
wanted to make the length of my meow file match the length of the note in a
melody. For longer notes, I used another method to find the number of times
I would need to duplicate a meow file.

```ruby
def number_of_loops(file_length, note_length)
  (note_length/file_length).ceil
end
```

After creating the looped file, I cropped it to the correct length:

```ruby
def crop_looped_file(looped_file, output_file, note_duration)
  cropped_loops = FFMPEG::Movie.new(looped_file)
  cropped_loops.transcode(output_file, ["-ss", "0", "-t", note_duration])
end
```

There was one big issue with this process. For a note that required the file to
be looped three times there would be three distinct cat meows instead of one
long, drawn-out meow. And the last one would likely be cut off at the end. So,
not exactly ideal.

![fail cat](https://images.thoughtbot.com/blog-vellum-image-uploads/amsUH3kQSG9chxsLW2EC_giphy.gif)

But also, I had a limited amount of time and it's not like perfecting 
Meowifier is going to save the world, so I'll get to fixing that one day. When I
_do_ fix it, I intend to split each meow into three parts-- beginning, middle,
and end. _Then_ I'll use something like the process above to duplicate and crop
the middle of the meow to get the right note length.

## The song builder

The song builder combines all the files and creates a new audio file.

```ruby
def combine
  Writer.new(@file_path, OUTPUT_FORMAT) do |writer|
    @collection.each do |file|
      Reader.new(file).each_buffer(SAMPLE_FRAMES_PER_BUFFER) do |buffer|
        writer.write(buffer)
      end
    end
  end
end
```

And voilà! Listen to my meowsterpiece:

<html>
    <center>
        <audio
            controls
            src="https://images.thoughtbot.com/blog-vellum-image-uploads/PdBTiqSNScC6l8aXLY8g_1535895032-4859%20copy.wav">
                Your browser does not support the
                <code>audio</code> element.
        </audio>
    </center>
</html>

![annoyed cat](https://images.thoughtbot.com/blog-vellum-image-uploads/G0k60iYHS02IR6AvnkFe_giphy.gif)

## There are some issues...

It turns out melody extraction is actually very difficult. The free or cheap
tools come up short. And despite the fact that _Meowifier_ will be worth
millions one day, I'm not too sure about shelling out a few thousand dollars for
professional grade melody extraction tools.

So, did I find a better tool? Did I end up spending thousands after all?
Is _Meowifier_ dead in the water? Tune in next time for the thrilling
conclusion.

![dramatic cat](https://images.thoughtbot.com/blog-vellum-image-uploads/4tJdFfvNSHaqpPd9AKGc_giphy.gif)
