{-# OPTIONS_GHC -threaded #-}
module Composition.Sound.Octaves (
octaveUp
, octaveDown
, liftInOctave
, liftInOctaveV
) where
import Data.Maybe (fromJust, mapMaybe)
import GHC.Arr
import GHC.List (iterate')
import Data.List hiding (iterate')
import Composition.Sound.Functional.Basics
octaveUp :: Float -> Float
octaveUp :: Float -> Float
octaveUp Float
x = Float
2 Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x
{-# INLINE octaveUp #-}
octaveDown :: Float -> Float
octaveDown :: Float -> Float
octaveDown Float
x = Float
x Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
2
{-# INLINE octaveDown #-}
liftInOctave :: Int -> Float -> Maybe Float
liftInOctave :: Int -> Float -> Maybe Float
liftInOctave Int
n Float
x
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
8 = Maybe Float
forall a. Maybe a
Nothing
| Float -> Float
closestNote Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
24.4996 =
case Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Int -> Int) -> (Float -> Maybe Int) -> Float -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> Maybe Int
whichOctave (Float -> Int) -> Float -> Int
forall a b. (a -> b) -> a -> b
$ Float
x) Int
n of
Ordering
EQ -> Float -> Maybe Float
forall a. a -> Maybe a
Just (Float -> Float
closestNote Float
x)
Ordering
LT -> let z :: Float
z = Float -> Float -> Float
forall a. Floating a => a -> a -> a
logBase Float
2.0 (Array Int Float -> Int -> Float
forall i e. Array i e -> Int -> e
unsafeAt Array Int Float
notes (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
12) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float -> Float
closestNote Float
x)
z1 :: Integer
z1 = Float -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate Float
z in
if Float -> Float
forall a. Num a => a -> a
abs (Float
z Float -> Float -> Float
forall a. Num a => a -> a -> a
- Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
z1) Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
0.999 Bool -> Bool -> Bool
|| Float -> Float
forall a. Num a => a -> a
abs (Float
z Float -> Float -> Float
forall a. Num a => a -> a -> a
- Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
z1) Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
0.001
then Float -> Maybe Float
forall a. a -> Maybe a
Just ([Float] -> Float
forall a. [a] -> a
last ([Float] -> Float) -> (Float -> [Float]) -> Float -> Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Float] -> [Float]
forall a. Int -> [a] -> [a]
take (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
z1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) ([Float] -> [Float]) -> (Float -> [Float]) -> Float -> [Float]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Float -> Float) -> Float -> [Float]
forall a. (a -> a) -> a -> [a]
iterate' Float -> Float
octaveUp (Float -> Float) -> Float -> Float
forall a b. (a -> b) -> a -> b
$ Float -> Float
closestNote Float
x)
else Float -> Maybe Float
forall a. a -> Maybe a
Just ([Float] -> Float
forall a. [a] -> a
last ([Float] -> Float) -> (Float -> [Float]) -> Float -> Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Float] -> [Float]
forall a. Int -> [a] -> [a]
take (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
z1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) ([Float] -> [Float]) -> (Float -> [Float]) -> Float -> [Float]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Float -> Float) -> Float -> [Float]
forall a. (a -> a) -> a -> [a]
iterate' Float -> Float
octaveUp (Float -> Float) -> Float -> Float
forall a b. (a -> b) -> a -> b
$ Float -> Float
closestNote Float
x)
Ordering
_ -> let z :: Float
z = Float -> Float -> Float
forall a. Floating a => a -> a -> a
logBase Float
2.0 (Float -> Float
closestNote Float
x Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Array Int Float -> Int -> Float
forall i e. Array i e -> Int -> e
unsafeAt Array Int Float
notes (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
12))
z1 :: Integer
z1 = Float -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
truncate Float
z in
if Float -> Float
forall a. Num a => a -> a
abs (Float
z Float -> Float -> Float
forall a. Num a => a -> a -> a
- Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
z1) Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
0.999 Bool -> Bool -> Bool
|| Float -> Float
forall a. Num a => a -> a
abs (Float
z Float -> Float -> Float
forall a. Num a => a -> a -> a
- Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
z1) Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
< Float
0.001
then Float -> Maybe Float
forall a. a -> Maybe a
Just ([Float] -> Float
forall a. [a] -> a
last ([Float] -> Float) -> (Float -> [Float]) -> Float -> Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Float] -> [Float]
forall a. Int -> [a] -> [a]
take (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
z1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) ([Float] -> [Float]) -> (Float -> [Float]) -> Float -> [Float]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Float -> Float) -> Float -> [Float]
forall a. (a -> a) -> a -> [a]
iterate' Float -> Float
octaveDown (Float -> Float) -> Float -> Float
forall a b. (a -> b) -> a -> b
$ Float -> Float
closestNote Float
x)
else Float -> Maybe Float
forall a. a -> Maybe a
Just ([Float] -> Float
forall a. [a] -> a
last ([Float] -> Float) -> (Float -> [Float]) -> Float -> Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Float] -> [Float]
forall a. Int -> [a] -> [a]
take (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
z1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) ([Float] -> [Float]) -> (Float -> [Float]) -> Float -> [Float]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Float -> Float) -> Float -> [Float]
forall a. (a -> a) -> a -> [a]
iterate' Float -> Float
octaveDown (Float -> Float) -> Float -> Float
forall a b. (a -> b) -> a -> b
$ Float -> Float
closestNote Float
x)
| Bool
otherwise = Maybe Float
forall a. Maybe a
Nothing
liftInOctaveV :: Int -> [Float] -> [Float]
liftInOctaveV :: Int -> [Float] -> [Float]
liftInOctaveV Int
n = (Float -> Maybe Float) -> [Float] -> [Float]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Int -> Float -> Maybe Float
liftInOctave Int
n)