-- |
-- Module      :  Composition.Sound.Functional.OvertonesO
-- Copyright   :  (c) OleksandrZhabenko 2021
-- License     :  MIT
-- Stability   :  Experimental
-- Maintainer  :  olexandr543@yahoo.com
--
-- Some variants of the f :: 'Float' -> 'OvertonesO' function that can be used for overtones
-- (and a timbre respectively) generation.

{-# LANGUAGE BangPatterns #-}
{-# OPTIONS_HADDOCK show-extensions #-}
{-# OPTIONS_GHC -threaded #-}

module Composition.Sound.Functional.OvertonesO where

import GHC.Arr
import Composition.Sound.Functional.Basics

{-| For the given frequency of the note it generates a list of the tuples, each one of which contains the harmonics' frequency
and amplitude. Is taken from the Composition.Sound.Functional.Basics module, so it must be imported qualified to be used with
the last one.   -}
overTones :: Float -> OvertonesO
overTones :: Float -> OvertonesO
overTones = Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG Int
1 Int
1 Int
2 Float
1.0
{-# INLINE overTones #-}

{-| A generalized variant of the 'overTones' function with just two additional control parameters (so represents a two-parameters additionally parameterized family of 'overTones' functions). -}
overTonesKN2 :: Int -> Int -> Float -> OvertonesO
overTonesKN2 :: Int -> Int -> Float -> OvertonesO
overTonesKN2 Int
k Int
n = Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG Int
k Int
n Int
2 Float
1.0
{-# INLINE overTonesKN2 #-}

{-| A generalized variant of the 'overTones' and 'overTonesKN2' with the possibility to specify the additional parameters for them.  -}
overTonesKNPG :: Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG :: Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG Int
k Int
n Int
p Float
amplK Float
note =
   ((Float, Float) -> Bool) -> OvertonesO -> OvertonesO
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (\(!Float
w,!Float
z) -> Float
w Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Array Int Float -> Int -> Float
forall i e. Array i e -> Int -> e
unsafeAt Array Int Float
notes Int
107 Bool -> Bool -> Bool
&& Float -> Float
forall a. Num a => a -> a
abs Float
z Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
0.001) (OvertonesO -> OvertonesO)
-> ([Int] -> OvertonesO) -> [Int] -> OvertonesO
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Float, Float) -> Bool) -> OvertonesO -> OvertonesO
forall a. (a -> Bool) -> [a] -> [a]
filter (\(Float
_,Float
z) -> Float -> Float
forall a. Num a => a -> a
abs Float
z Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
1.0) (OvertonesO -> OvertonesO)
-> ([Int] -> OvertonesO) -> [Int] -> OvertonesO
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Float, Float)) -> [Int] -> OvertonesO
forall a b. (a -> b) -> [a] -> [b]
map (\Int
i ->
    (Float
note Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Num a => a -> a
abs (Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k)), Float
amplK Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product ([Int] -> Int) -> (Int -> [Int]) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate Int
p (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n)))) ([Int] -> OvertonesO) -> [Int] -> OvertonesO
forall a b. (a -> b) -> a -> b
$ [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n..Int
40000 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int -> Int
forall a. Num a => a -> a
abs Int
n]

{-| A generalized variant of the 'overTones' and 'overTonesKN2' with the possibility to specify the additional parameters for them. Otherwise than the similar 'overTonesKNPG', it can generate the higher overtones than the B8 to the 20000 Hz.  -}
overTonesKNPG20k :: Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG20k :: Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG20k = (Float -> Float)
-> Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG20kF Float -> Float
forall a. a -> a
id
{-# INLINE overTonesKNPG20k #-}

{-| A generalized variant of the 'overTonesKNPG20k' with the possibility to specify the additional function to control the overtones amplitudes. Otherwise than the similar 'overTonesKNPG', it can generate the higher overtones than the B8 to the 20000 Hz. The first argument, the function @f@ is intended to be a monotonic growing one though it can be not necessary. -}
overTonesKNPG20kF :: (Float -> Float) -> Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG20kF :: (Float -> Float)
-> Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG20kF Float -> Float
f = (Float -> Float)
-> (Int -> Int)
-> Int
-> Int
-> Int
-> Float
-> Float
-> OvertonesO
overTonesKNPG20kFALaClarinet Float -> Float
f Int -> Int
forall a. a -> a
id
{-# INLINE overTonesKNPG20kF #-}

{-| Is taken from the Composition.Sound.Functional.Basics module, so it must be imported qualified to be used with
the last one. -}
overTonesALaClarinet :: Float -> OvertonesO
overTonesALaClarinet :: Float -> OvertonesO
overTonesALaClarinet Float
note =
  ((Float, Float) -> Bool) -> OvertonesO -> OvertonesO
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (\(!Float
w,!Float
z) -> Float
w Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Array Int Float -> Int -> Float
forall i e. Array i e -> Int -> e
unsafeAt Array Int Float
notes Int
107 Bool -> Bool -> Bool
&& Float -> Float
forall a. Num a => a -> a
abs Float
z Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
0.001) (OvertonesO -> OvertonesO)
-> ([Integer] -> OvertonesO) -> [Integer] -> OvertonesO
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> (Float, Float)) -> [Integer] -> OvertonesO
forall a b. (a -> b) -> [a] -> [b]
map (\Integer
i ->
    (Float
note Float -> Float -> Float
forall a. Num a => a -> a -> a
* Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1), Float
1 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)))) ([Integer] -> OvertonesO) -> [Integer] -> OvertonesO
forall a b. (a -> b) -> a -> b
$ [Integer
0..Integer
512]

{-| A generalized variant of the 'overTonesKNPG20k' with the possibility to specify the additional function to control the overtones amplitudes. Otherwise than the similar 'overTonesKNPG', it can generate the higher overtones than the B8 to the 20000 Hz. The first argument, the function @f@ is intended to be a monotonic growing one though it can be not necessary. The second one parameter -- the @g@ function can be simply (*2), (*4) or something else and also is intended to be monotonic. -}
overTonesKNPG20kFALaClarinet :: (Float -> Float) -> (Int -> Int) -> Int -> Int -> Int -> Float -> Float -> OvertonesO
overTonesKNPG20kFALaClarinet :: (Float -> Float)
-> (Int -> Int)
-> Int
-> Int
-> Int
-> Float
-> Float
-> OvertonesO
overTonesKNPG20kFALaClarinet Float -> Float
f Int -> Int
g Int
k Int
n Int
p Float
amplK Float
note =
   ((Float, Float) -> Bool) -> OvertonesO -> OvertonesO
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (\(!Float
w,!Float
z) -> Float
w Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
20000.0 Bool -> Bool -> Bool
&& Float -> Float
forall a. Num a => a -> a
abs Float
z Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
0.001) (OvertonesO -> OvertonesO)
-> ([Int] -> OvertonesO) -> [Int] -> OvertonesO
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Float, Float) -> Bool) -> OvertonesO -> OvertonesO
forall a. (a -> Bool) -> [a] -> [a]
filter (\(Float
_,!Float
z) -> Float -> Float
forall a. Num a => a -> a
abs Float
z Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
<= Float
1.0) (OvertonesO -> OvertonesO)
-> ([Int] -> OvertonesO) -> [Int] -> OvertonesO
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> (Float, Float)) -> [Int] -> OvertonesO
forall a b. (a -> b) -> [a] -> [b]
map (\Int
i ->
    (Float
note Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Num a => a -> a
abs (Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int
g Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k)), Float -> Float
f (Float
amplK Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product ([Int] -> Int) -> (Int -> [Int]) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate Int
p (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n))))) ([Int] -> OvertonesO) -> [Int] -> OvertonesO
forall a b. (a -> b) -> a -> b
$ [Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n..]