Safe Haskell  None 

Representation for scales, pitches, and frequencies (note numbers).
There are many representations for a pitch, at many different levels of abstraction.
 newtype Note = Note Text
 note_text :: Note > Text
 data Pitch = Pitch {
 pitch_octave :: !Octave
 pitch_degree :: !Degree
 pitch :: Enum pc => Octave > pc > Pitch
 data Degree = Degree {}
 type Octave = Int
 type PitchClass = Int
 type Accidentals = Int
 type Semi = Int
 type FSemi = Double
 type Step = Int
 pitch_accidentals :: Pitch > Accidentals
 pitch_pc :: Pitch > PitchClass
 add_octave :: Octave > Pitch > Pitch
 add_pc :: PitchClass > PitchClass > Pitch > Pitch
 subtract_pitch :: PitchClass > Pitch > Pitch > PitchClass
 middle_octave :: Octave
 middle_c :: Pitch
 data Input = Input !KbdType !Pitch !Frac
 data KbdType
 type Frac = Double
 newtype NoteNumber = NoteNumber Double
 nn :: Real a => a > NoteNumber
 nn_to_double :: NoteNumber > Double
 nns_equal :: NoteNumber > NoteNumber > Bool
 type Hz = Double
 add_hz :: Hz > NoteNumber > NoteNumber
 modify_hz :: (Hz > Hz) > NoteNumber > NoteNumber
 nn_to_hz :: NoteNumber > Hz
 hz_to_nn :: Hz > NoteNumber
 middle_c_hz :: Hz
 newtype ScaleId = ScaleId Text
 empty_scale :: ScaleId
 twelve :: ScaleId
 data Transpose
 zero_transpose :: Transpose > Bool
 modify_transpose :: (Double > Double) > Transpose > Transpose
 newtype Key = Key Text
 key_text :: Key > Text
Note
A Note is the most abstract representation of pitch, in that it's simply an unparsed bit of text representing that pitch. Given a Scale, it's expected to name a val call exported by that scale.
Pitch
A Pitch is a parsed Note
. Functions that want to manipulate notes
in a scaleindependent way can ask the scale to convert to and from a Note.
Not all scales use all the fields.
Pitch  

A scale degree, without reference to an octave.
Degree  

type PitchClass = Int Source #
A PitchClass maps directly to a scale degree, which is a letter in traditional Western notation, though this PitchClass may have fewer or greater than 7 notes. The PitchClass is absolute in that it doesn't depend on the tonic of a key.
These numbers are expected to wrap around at the octave, so they usually use
modular arithmetic, but if an octave is not handy (i.e. they're not in
a Pitch
), then steps exceeding an octave will be wrapped into an octave
when one is available.
type Accidentals = Int Source #
Positive for sharps, negative for flats.
Number of semitones. This is an absolute measure from octave 0,
regardless of whether the scale has notes at octave 0. This is so you can
convert between Semis and the similarly absolute Pitch
in the same way for
all scales.
This is a relative amount of transposition. It could be either chromatic or diatonic.
pitch_accidentals :: Pitch > Accidentals Source #
pitch_pc :: Pitch > PitchClass Source #
add_pc :: PitchClass > PitchClass > Pitch > Pitch Source #
Add diatonic steps. This doesn't deal with key signatures or nondiatonic scales.
subtract_pitch :: PitchClass > Pitch > Pitch > PitchClass Source #
middle_octave :: Octave Source #
The middle octave. The "center" of a scale should be oriented around this.
Input
A physically played note on some input device. This hasn't been mapped to a scale yet, so the Pitch is in the context of the device's layout.
I have 3 kinds of kbds:
ASCII has 10 white keys, and black keys between each one. It should be relative, so that C or sa is always on Q and Z, and if the octave is <10 then it will wrap on the same row.
MIDI has the usual piano layout. It's absolute, so that a relative scale can start at keys other than C, if that would be convenient for the layout. The octave is rounded up to the nearest multiple of 7, and the extra keys are unused, so the octave always starts at C.
Continuum has no keys, just NNs. So it gets the scale degree that's closest to the given NN. That's different from the MIDI kbd because the MIDI kbd never wants a key to emit something between notes. TODO not supported yet
PianoKbd  An absolute kbd maps the same key to the same absolute pitch, regardless of the key. This is the case for a piano style kbd. This is consistent with convention, but also the piano kbd has a fixed layout of white and black keys. So if you e.g. transpose Amajor to start on C, then you have a mysterious black key in between B and C, and no way to play C#. 
AsciiKbd  A relative kbd always maps the same key to the same relative pitch. This is appropriate for the ASCII kbd, because it has "black keys" between every white key, so scales can be transposed freely. 
A number between 1 and 1 exclusive, representing the portion of the way between two scale degrees. I could have used "Cents" for this, but that implies equal temperedness.
NoteNumber
newtype NoteNumber Source #
This is equal tempered scale notes with the same definition as MIDI, so MIDI note 0 is NoteNumber 0, at 8.176 Hz, and is 1c. Middle C (4c) is NoteNumber 60.
PSignal
s are converted into this before performance
since performance doesn't understand scales.
nn :: Real a => a > NoteNumber Source #
nn_to_double :: NoteNumber > Double Source #
nns_equal :: NoteNumber > NoteNumber > Bool Source #
True if the NoteNumbers are close enough that they sound the same.
Hz
add_hz :: Hz > NoteNumber > NoteNumber Source #
modify_hz :: (Hz > Hz) > NoteNumber > NoteNumber Source #
nn_to_hz :: NoteNumber > Hz Source #
hz_to_nn :: Hz > NoteNumber Source #
Negative hz will result in NaN. TODO take an abs or throw an error, or let the NaN propagate?
middle_c_hz :: Hz Source #
Scale
empty_scale :: ScaleId Source #
Usually this means to use the scale currently in scope.
A generic transposition, for operations that can transpose diatonically, chromatically, or by absolute NoteNumber.
Chromatic Double  
Diatonic Double  
Nn Double  Nn is scaleindependent, so it's not suitable for symbolic transposition, but it's still useful for pitch transposition. 
Eq Transpose #  
Ord Transpose #  
Show Transpose #  
Pretty.Pretty Transpose #  
ShowVal.ShowVal Transpose #  
ToVal Transpose #  
TypecheckNum Transpose #  
ToVal Transpose #  
Typecheck Transpose #  VNums can also be coerced into chromatic transposition, so you can write a plain number if you don't care about diatonic. This is different from 
zero_transpose :: Transpose > Bool Source #
Diatonic transposition often requires a Key for context.
This is not very strongly typed, because it's intended to be scale independent, and not every scale will have the same values for key and mode.