--@client --@include /libs/task.txt local Task = require('/libs/task.txt') local Sound = class('Sound') local function map(x, a, b, c, d) return (x - a) / (b - a) * (d - c) + c end local function fade(n, min, mid, max) if n < min or n > max then return 0 end if n > mid then min = mid - (max - mid) end return math.cos((1 - ((n - min) / (mid - min))) * (math.pi / 2)) end function Sound:initialize(redline, parent, sounds) local sounds = sounds or { [900] = 'https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_idle.ogg', [2500] = 'https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_on_2500.ogg', [4000] = 'https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_on_4000.ogg', [6750] = 'https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_on_6750.ogg', [8500] = 'https://raw.githubusercontent.com/koptilnya/gmod-data/main/engine_sounds/bmw_s54/ext_e30s54_on_8500.ogg', } local redline = redline or 7000 self.active = false local soundObjects = {} local soundRpms = {} local maxValue = 0 local throttle = 0 local engineRpm = 0 local smoothRpm = 0 local smoothThrottle = 0 Task.run(function() for soundRpm, soundPath in pairs(sounds) do local sound = await * soundLoad(soundPath, '3d noblock noplay') soundObjects[soundRpm] = sound table.insert(soundRpms, soundRpm) if maxValue < soundRpm then maxValue = soundRpm end end table.sort(soundRpms) hook.add('think', table.address({}), function() if not self.active then return end smoothRpm = smoothRpm * (1 - 0.2) + engineRpm * 0.2 smoothThrottle = smoothThrottle * (1 - 0.1) + throttle * 0.1 for n, rpm in ipairs(soundRpms) do if not soundObjects[rpm] or not soundObjects[rpm].Bass then goto CONTINUE end local min = n == 1 and -100000 or soundRpms[n - 1] local max = n == #soundRpms and 100000 or soundRpms[n + 1] local c = fade(smoothRpm, min - 10, rpm, max + 10) local vol = c * map(smoothThrottle, 0, 1, 0.5, 1) local soundObject = soundObjects[rpm].Bass soundObject:setVolume(vol) soundObject:setPitch(smoothRpm / rpm) soundObject:setPos(parent:getPos()) soundObject:pause() soundObject:play() ::CONTINUE:: end end) end) net.receive('ENGINE_FULLRPM', function() local rpm = net.readUInt(16) engineRpm = rpm * (maxValue / redline) throttle = math.max(net.readFloat(), 0) end) end return Sound