Skip to content

Latest commit

 

History

History
105 lines (74 loc) · 3.37 KB

haskell.md

File metadata and controls

105 lines (74 loc) · 3.37 KB

Playing music on Linux

Getting started with MIDI was my primary source: It has detailed instructions on how to get MIDI played on a Linux box.

Install a midi file player. This actually came out-of-the-box in my linux distro (Xubuntu 11.10):

$ sudo apt-get install aplaymidi

Install a software MIDI synthesizer (I don't have and don't know how to use a hardware synthesizer). this will install both a command-line and a Qt-based synthesizer called =qsynth=.

$ sudo apt-get install fluidsynth

Install [[http://jackaudio.org/][Jackaudio daemon]] software, seems useful to route output of MIDI synthesizer to actual hardware soundcard and abstract away from the gory details of sound playing on linux and other platforms. There is a an accompanying QT-based controller:

$ sudo apt-get install jackd qjacktctl

Optionally, install [[http://www.rosegardenmusic.com/][rosegarden]], a sequencer for creating, recording and playing soundtracks and music.

Creating music with Haskell

Making Noise

First, we want to be able to make some sound. What is sound? Sound is simply a stream of binary data that is sent to some audio device sampling a sound wave. So we need a sampling rate (in Hz) which is the number of samples per second, here a CD quality rate:

samplingRate = 44100

Now, let's make a sound. We will use the Karplus-Strong algorithm to synthesize a sound mimicking a string (eg. a guitar):

ks freq noise = s where s = take (samplingRate div freq) noise

The algorithm works as a feedback loop that takes some white noise (eg. random noise) during an initial period then feed it to some filter.

     ++ loPass s

Here the filter is a so-called low-pass filter that averages two successive samples, that produces a plucked-string sound:

loPass (x:y:xs) = 0.5*(x+y):loPass (y:xs)

We can also use another filter that shall produced a drum sound, using some random stream to select the averaging coefficient:

drum (x:y:xs) (r:rs) | r < 0.5 = 0.5*(x+y): drum (y:xs) | otherwise = -0.5*(x+y): drum (y:xs)

toByteString = BS.pack . map (fromIntegral . floor . (255 *))

main = do g <- getStdGen BS.putStr $ slice 2 $ toByteString $ ks 440 $ randomRs (0.0 :: Double, 1.0) g

Music Theory Crash Course

A single note is a pitch, an octave and a duration which is a fraction of the basic tempo:

data Note = Note Pitch Octave Duration

type Octave = Int

type Duration = Int

data Pitch = C | C♯ | D♭ | D | D♯ | E♭ | E | E♯ | F♭ | F | F♯ | G♭ | G | G♯ | A♭ | A | A♯ | B♭ | B | B♯ | C♭ deriving (Eq, Show, Read)

To make sound from a note, we need to derive a sequence of bytes representing the soundwave, encoded in RAW format to send to our sound player.