module Nes.APU.Mixer (getMixerOutput) where

import Nes.APU.State
import Nes.APU.State.DMC (getDMCOutput)
import Nes.APU.State.Noise (getNoiseOutput)
import Nes.APU.State.Pulse (getPulseOutput)
import Nes.APU.State.Triangle (getTriangleOutput)
import Prelude hiding (cycle)

getMixerOutput :: APUState -> Float
getMixerOutput :: APUState -> Float
getMixerOutput MkAPUState{Float
Int
FilterThread
FrameCounter
Noise
Pulse
Triangle
DMC
Float -> IO ()
_frameCounter :: FrameCounter
_pulse1 :: Pulse
_pulse2 :: Pulse
_triangle :: Triangle
_noise :: Noise
_dmc :: DMC
_cycle :: Int
_filterThread :: FilterThread
_sampleTimer :: Float
_samplePeriod :: Float
_pushSampleCallback :: Float -> IO ()
_pushSampleCallback :: APUState -> Float -> IO ()
_samplePeriod :: APUState -> Float
_sampleTimer :: APUState -> Float
_filterThread :: APUState -> FilterThread
_cycle :: APUState -> Int
_dmc :: APUState -> DMC
_noise :: APUState -> Noise
_triangle :: APUState -> Triangle
_pulse2 :: APUState -> Pulse
_pulse1 :: APUState -> Pulse
_frameCounter :: APUState -> FrameCounter
..} =
    let
        !pulse1Out :: Int
pulse1Out = Pulse -> Int
getPulseOutput Pulse
_pulse1
        !pulse2Out :: Int
pulse2Out = Pulse -> Int
getPulseOutput Pulse
_pulse2
        !triangleOut :: Int
triangleOut = Triangle -> Int
getTriangleOutput Triangle
_triangle
        !noiseOut :: Int
noiseOut = Noise -> Int
getNoiseOutput Noise
_noise
        !dmcOut :: Int
dmcOut = DMC -> Int
getDMCOutput DMC
_dmc
        !pulseOut :: Float
pulseOut = Int -> Float
pulseTable (Int
pulse1Out Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
pulse2Out)
        !tndOut :: Float
tndOut = Int -> Float
tndTable (Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
triangleOut Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
noiseOut Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dmcOut)
        !mixerOutput :: Float
mixerOutput = Float
pulseOut Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
tndOut
     in
        Float
mixerOutput

{-# INLINE pulseTable #-}
pulseTable :: Int -> Float
pulseTable :: Int -> Float
pulseTable Int
0 = Float
0
pulseTable Int
n = Float
95.52 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ ((Float
8128.0 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
100)

{-# INLINE tndTable #-}
tndTable :: Int -> Float
tndTable :: Int -> Float
tndTable Int
0 = Float
0
tndTable Int
n = Float
163.67 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ ((Float
24329.0 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
100)