Phillip Trelford's Array

POKE 36879,255

Tremolo

This week I added a simple tremolo effect to my mini-keyboard project Monokeys. Tremolo is a trembling effect, and sometimes seen in Low Frequency Oscillators.


I found an example of Coding some Tremolo and wrote the formula as an F# function:

let tremolo freq depth i = (1.0 - depth) + depth * (sineWave freq i) ** 2.0


Then I added sliders for the frequency and depth to compose the shape of a sound:

let tremolo i = tremolo tremoloFreq.Value tremoloDepth.Value i
let shape i = sineWave freq i * fadeOut i * tremolo i

Full source code is available on BitBucket: https://bitbucket.org/ptrelford/monokeys

Monokeys

Press a key to hear a note:


GAFBB should sound familiar to fans of 70s sci-fi.

I wanted to programmatically generate sound effects for a retro game I’m working on. Generating wave files using F# turned out to be less than 30 lines of code:

open System.IO

/// Write WAVE PCM soundfile (8KHz Mono 8-bit)
let write stream (data:byte[]) =
    use writer = new BinaryWriter(stream)
    // RIFF
    writer.Write("RIFF"B)
    let size = 36 + data.Length in writer.Write(size)
    writer.Write("WAVE"B)
    // fmt
    writer.Write("fmt "B)
    let headerSize = 16 in writer.Write(headerSize)
    let pcmFormat = 1s in writer.Write(pcmFormat)
    let mono = 1s in writer.Write(mono)
    let sampleRate = 8000 in writer.Write(sampleRate)
    let byteRate = sampleRate in writer.Write(byteRate)
    let blockAlign = 1s in writer.Write(blockAlign)
    let bitsPerSample = 8s in writer.Write(bitsPerSample)
    // data
    writer.Write("data"B)
    writer.Write(data.Length)
    writer.Write(data)

let sample x = (x + 1.)/2. * 255. |> byte 

let data = Array.init 16000 (fun i -> sin (float i/float 8) |> sample)
let stream = File.Create(@"C:\tone.wav")
write stream data

F#’s ASCII string support and light syntax, combined with .Net’s convenient BinaryWriter class made this ridiculously easy.

Then just for fun I created the simple keyboard in 70 lines of code:

namespace MonoKeys

open System
open System.Windows
open System.Windows.Controls
open Microsoft.Xna.Framework.Audio

type App() as this = 
    inherit Application()

    let sampleRate = 8000

    let sample x = x * 32767. |> int16

    let toBytes (xs:int16[]) =
        let bytes = Array.CreateInstance(typeof<byte>, 2 * xs.Length)
        Buffer.BlockCopy(xs, 0, bytes, 0, 2 * xs.Length)
        bytes :?> byte[]

    let create freq =
        let samples = 12000
        let sine i = sin (Math.PI * 2. * float i / float sampleRate * freq)
        let fadeOut i = float (samples-i) / float samples
        Array.init samples (fun i -> sine i * fadeOut i |> sample)
        |> toBytes

    let play freq =        
        let bytes = create freq
        let effect = new SoundEffect(bytes, sampleRate, AudioChannels.Mono)
        effect.Play() |> ignore
    
    let notes = [
        "A", 220.00
        "A#", 233.08
        "B", 246.94
        "C", 261.63
        "C#", 277.18
        "D", 293.66
        "D#", 311.13
        "E", 329.63
        "F", 349.23
        "F#", 369.99
        "G", 392.00
        "G#", 415.30
        "A", 440.00
        "A#", 466.16
        "B", 493.88
        "C", 523.25
        "C#", 554.37
        "D", 587.33]

    let keys =
        notes |> Seq.map (fun (text,freq) ->
            let key = Button(Content=text)
            key.Click.Add(fun _ -> play freq)
            key
        )

    let grid = Grid()
    do  keys |> Seq.iteri (fun i key ->
            grid.ColumnDefinitions.Add(ColumnDefinition())
            Grid.SetColumn(key,i)
            grid.Children.Add key
        )

    do  this.Startup.AddHandler(fun o e -> this.RootVisual <- grid)


This time Silverlight 5’s SoundEffect class makes generating sounds easy accepting an array of bytes. I simply copied the notes from the web, formatted the text as tuples and mapped them to buttons that showed the text and played a note of the specified frequency. The keys were then laid out on a grid. Look no XAML ;)

Next I’m planning to add some more features to generate sounds like a synthesizer maybe one day like my monotribe

If you’re interested in programming and sound I’d recommend taking a look at Sam Aaron’s Overtone for Clojure and Rob Pickering’s Undertone for F#.

Rob will be running a session on Undertone at this year’s Progressive F# Tutorials in London:

progressivefsharplondon2013

Pissed off owls

Last night Neil Danson gave a great presentation on F# on iPad and iPhone in Xamarin Studio at the F#unctional Londoners meetup hosted by Skills Matter. Xamarin announced that they were working towards first-class F# support at their recent Evolve conference, and that support is currently in Beta. Xamarin Studio is an IDE that runs on Mac, Linux and Windows and lets you target iOS and Android.

Easy to follow instructions: Use F# for iOS development

Neil showed how to build a movie database application using the IMDB API that runs on iPad and iPhone in just over 100 lines. It makes use of F# Object Expressions and Async Workflows. The source if available on Bitbucket: https://bitbucket.org/thedo666/imdb

One of the really impressive parts is the readability, the following statement taken from the code composes the application:

start ==> search ==> show_results ==> open_web_page ==> finish

The next demo was a game with the imaginative title “Pissed off owls”, that lets you launch incensed rotund avians at obstacles with physics. Again the source code is just over 100 lines and available on Bitbucket: https://bitbucket.org/thedo666/pissed-off-owls

Pissed off owls

It is written with MonoGame and uses the Farseer physics engine. Here’s the code to set up the scene:

let player = Actor("Owl",Position(30.f,8.f), Circle, Player, Dynamic)
let level =  [ Actor("Background", Position(160.f,120.f), Box, Ignore, None)
                Actor("Catapult", Position(70.f,32.f), Box, Ignore, None)
                Actor("Mouse", Position(185.f,15.f), Circle, Enemy, Dynamic)
                Actor("Mouse", Position(285.f, 15.f), Circle, Enemy, Dynamic)
                Actor("Tower", Position(225.f, 64.f), Box, Prop, Dynamic) ]

The video to the talk should be available later today: http://skillsmatter.com/podcast/scala/f-on-ipad-and-iphone-with-xamarin-studio

Neil Danson

Another demo showed briefly at the end was PacMan, written in F# and running on iPad. The source code is available on Bitbucket: https://bitbucket.org/thedo666/pacman

Pacman iOS

It’s a port of some code I wrote for a Coding Kata last year, it also runs on Windows in Silverlight, WPF, Windows 8 and Windows Phone. Play it here: http://trelford.com/blog/post/PacTile.aspx

Want to learn more about MonoTouch F#, I’d recommend Dave Thomas’s short series:

    Want to go to an event where YOU write games, Dublin GameCraft is coming to London in August!