Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Spectrum view of the effect nonlinear distortion has on various sound signals
import Numeric.FFT.Vector.Invertible
import Data.Vector.Unboxed (Vector)
import qualified Data.Vector.Generic as GA
import Data.Complex (magnitude)
import Data.Function ((&))
import Graphics.Dynamic.Plot.R2
main :: IO ()
main = do
plotWindow . distortionCompare $ sineSig 163 ^+^ sineSig 308
plotWindow . distortionCompare $ stringSig 100
plotWindow . distortionCompare $ stringSig (note "A2") ^+^ stringSig (note "E3")
plotWindow . distortionCompare $ stringSig (note "C3") ^+^ stringSig (note "E3")
plotWindow . distortionCompare $ stringSig (note "C3") ^+^ stringSig (5/4*note "C3")
plotWindow . distortionCompare $ stringSig (note "B2") ^+^ stringSig (note "F3")
plotWindow . distortionCompare $ stringSig (note "B2") ^+^ stringSig (7/5*note "B2")
return ()
type = Double
type Signal = Vector
type Freq =
signalPlot, spectrumPlot :: Signal -> DynamicPlottable
signalPlot sig = lineSegPlot
$ zip [0,1/fromIntegral n..] (GA.toList sig)
where n = GA.length sig
spectrumPlot sig = lineSegPlot
$ zip [0..800] ((2/fromIntegral n*) . magnitude <$> GA.toList spectrum)
where spectrum = run dftR2C sig
n = GA.length sig
distortion :: Signal -> Vector
distortion = GA.map (tanh . (*4))
distortionCompare :: Signal -> [DynamicPlottable]
distortionCompare sig
= [ spectrumPlot sig & legendName "Original"
, spectrumPlot (distortion sig) & legendName "Distorted" ]
sineSig :: Freq -> Signal
sineSig ν = GA.generate n $ \i
-> sin (2 * pi * ν*fromIntegral i/fromIntegral n) / 2
where n = samplingFreq
stringSig :: Freq -> Signal
stringSig ν = GA.generate n $ \i ->
tan (sin (2 * pi * ν*fromIntegral i/fromIntegral n) * 1.3) / 3
+ tan (sin (4 * pi * ν*fromIntegral i/fromIntegral n)) / 2
where n = samplingFreq
samplingFreq :: Int
samplingFreq = 44100
note :: String -> Freq
note (nn:octv) = 440 * 2**(read octv - 4 + fromIntegral pitchClass/12)
where pitchClass = round $ fromIntegral ((fromEnum nn - fromEnum 'C')`mod`7 - 1) * 12/7 - 7
infixl 6 ^+^
(^+^) :: Signal -> Signal -> Signal
(^+^) = GA.zipWith (+)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.