module Effects where import Data.List import Types addEffects :: [DSPEffect] -> SampledSignal -> SampledSignal addEffects = foldr (.) id applyEffectToInterval :: (Seconds, Seconds) -> SampledSignal -> DSPEffect -> SampledSignal applyEffectToInterval (from, to) signal effect -- assert that from >= 0, to - from >= 0, to <= length signal and simply return original signal if constraints aren't met | from < 0 || from > to || samplesPerSecond to > length signal = signal | otherwise = samplesBefore ++ samplesDuring ++ samplesAfter where samplesBefore = take nSamplesBefore signal -- unaffected samplesDuring = effect $ take nSamplesDuring $ drop nSamplesBefore signal -- effected samplesAfter = drop (nSamplesBefore + nSamplesDuring) signal -- unaffected nSamplesBefore = samplesPerSecond from nSamplesDuring = samplesPerSecond (to - from) {- applyEffectToInterval :: (Seconds, Seconds) -> SampledSignal -> DSPEffect -> SampledSignal applyEffectToInterval (from, to) signal effect -- assert that from >= 0, to - from >= 0, to <= length signal and simply return original signal if constraints aren't met | from < 0 || from > to || samplesPerSecond to > length signal = signal | otherwise = samplesBefore ++ take nSamplesDuring samplesDuring ++ samplesOverlap ++ drop overlap samplesAfter where samplesBefore = take nSamplesBefore signal -- unaffected samplesDuring = effect $ take nSamplesDuring $ drop nSamplesBefore signal -- effected samplesAfter = drop (nSamplesBefore + nSamplesDuring) signal -- unaffected samplesOverlap = map sum $ transpose [drop nSamplesDuring samplesDuring, take overlap samplesAfter] nSamplesBefore = samplesPerSecond from nSamplesDuring = samplesPerSecond (to - from) overlap = length samplesDuring - nSamplesDuring -} gain :: Double gain = 2.0 clippingThreshold :: Double clippingThreshold = 0.8 clip :: Double -> DSPEffect clip threshold = map (\sample -> if sample > 0 then min threshold sample else max (negate threshold) sample) -- clip positive and negative samples addGain :: Double -> DSPEffect addGain value = map (* value) distortion :: DSPEffect distortion = clip clippingThreshold . addGain gain -- add more effects here -- works meh when applied to an interval echo :: DSPEffect echo prev = map sum $ transpose [prev, map (/ 1.5) $ delay 0.15 prev] delay :: Double -> DSPEffect delay n prev = replicate (samplesPerSecond n) 0 ++ prev -- 10 - 100 sounds decent-ish reduceSmplRate :: Int -> DSPEffect reduceSmplRate n prev = concatMap (replicate n) (shortener prev) where shortener [] = [] shortener xs = head xs : shortener (drop n xs) -- cuts every sample after the log(n)-th decimal place reduceResolution :: Double -> DSPEffect reduceResolution n = map (\x -> fromInteger (truncate (x * n)) / n)