Skip to content

Commit

Permalink
Use middle C = C4
Browse files Browse the repository at this point in the history
This retains compatibility with danigb's soundfont player
  • Loading branch information
newlandsvalley committed Oct 27, 2017
1 parent fa00e4c commit aeec081
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 14 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ This is an experimental complete re-write of the soundfont library. Although st

A SoundFont can be loaded from Benjamin Gleitzman's package of [pre-rendered sound fonts](https://github.com/gleitz/midi-js-soundfonts) or from a resource on the local server. It is then decoded into a dictionary of Audio Buffers (one for each note). A succession of notes can then be played through these buffers.

This is intended to be functionally equivalent to purescript-polymorphic soundfonts. The major difference from a user perspective is that the soundfonts are no longer implicit and have to be stored by the user and passed to the __playNote__ functions. The rarely used function to get the current time from the Audio Context has been dropped.
The conversion of a Gleitzman note name (e.g. Ab4) to a MIDI pitch uses middle C = C4.

This is intended to be functionally equivalent to purescript-polymorphic soundfonts. The major difference from a user perspective is that the soundfonts are no longer implicit and have to be stored by the user and passed to the __playNote__ functions. The rarely used function to get the current time from the Audio Context has been dropped.

## Build

bower install
pulp build

## Example

./build-example.sh

host on your web server and then navigate to dist/index.html
host on your web server and then navigate to dist/index.html
21 changes: 15 additions & 6 deletions src/Audio/SoundFont/Gleitz.purs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Audio.SoundFont.Gleitz (
) where


import Prelude (class Show, (<>), ($), (+), (*), map, negate, show)
import Prelude (class Show, (<>), ($), (+), (-), (*), map, negate, show)
import Data.String.Regex as Regex
import Data.String.Regex.Flags (noFlags)
import Data.String (toUpper)
Expand Down Expand Up @@ -72,22 +72,31 @@ midiPitch1 s =
let
mpitch :: Maybe Int
mpitch = case index matches 1 of -- first match group
Just (Just p) -> lookup p semitones
Just (Just p) -> lookup p semitones -- A-G
_ -> Nothing
acc :: Int
acc = case index matches 2 of -- second match group
Just (Just "b") -> (-1)
Just (Just "b") -> (-1) -- # or b
Just (Just "#") -> 1 -- # or b
_ -> 0
moctave :: Maybe Int
moctave = -- third match group
case index matches 3 of
case index matches 3 of -- octave number
Just (Just octave) -> fromString octave
_ -> Nothing
in
case (Tuple mpitch moctave) of
(Tuple (Just p) (Just oct)) -> Just ((12 * oct) + p + acc)
(Tuple (Just p) (Just oct)) -> Just $ toMidiPitch oct p acc
_ -> Nothing

-- | build a MIDI pitch (middle C = C4)
-- | building from the octave number, pitch (relative to C)
-- | and any accidental offset (i.e. flat lowers pitch by 1, sharp raised it)
-- | The MIDI standard does not standardise on a particular middle C
toMidiPitch :: Int -> Int -> Int -> Int
toMidiPitch octave pitch accidental =
(12 * octave) + pitch + accidental - 12

lookupPitch :: Pitch -> Maybe Int
lookupPitch p =
lookup (toUpper p) semitones
Expand All @@ -101,7 +110,7 @@ gleitzNoteName s =
let
makeRegex :: Partial => Regex.Regex
makeRegex =
case Regex.regex "([A-Ga-g])(b?)([0-8])" noFlags of
case Regex.regex "([A-Ga-g])([b#]?)([0-8])" noFlags of
Right r ->
r
regex = unsafePartial makeRegex
Expand Down
14 changes: 9 additions & 5 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ import Audio.SoundFont.Gleitz (midiPitch)
gleitzSuite :: forall t. Free (TestF t) Unit
gleitzSuite =
suite "gleitz" do
test "midi pitch Bb0" do
Assert.equal 10 (midiPitch "Bb0")
test "midi pitch A3" do
Assert.equal 45 (midiPitch "A3")
test "midi pitch C4" do
Assert.equal 36 (midiPitch "C4")
test "midi pitch Bb1" do
Assert.equal 10 (midiPitch "Bb1")
test "midi pitch A#1" do
Assert.equal 10 (midiPitch "A#1")
test "midi pitch A4" do
Assert.equal 45 (midiPitch "A4")
test "midi pitch C8" do
Assert.equal 96 (midiPitch "C8")
Assert.equal 84 (midiPitch "C8")

main :: forall t.
Eff
Expand Down

0 comments on commit aeec081

Please sign in to comment.