major rework
This commit is contained in:
110
Car simulation/Audio/EngineSound.cs
Normal file
110
Car simulation/Audio/EngineSound.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using SFML.Audio;
|
||||
using SFML.System;
|
||||
using System;
|
||||
|
||||
namespace Car_simulation.Audio
|
||||
{
|
||||
public class EngineSound : SoundStream
|
||||
{
|
||||
private const uint SAMPLE_RATE = 44100;
|
||||
private const ushort CHANNELS = 2;
|
||||
private const float BUFFER_DURATION = 0.01f;
|
||||
|
||||
private volatile float _currentRPM = 800f;
|
||||
private volatile float _currentThrottle = 0f;
|
||||
private float _volume = 0.3f;
|
||||
private bool _isPlaying = false;
|
||||
|
||||
private readonly int _cylinders = 4;
|
||||
private readonly Random _rand = new Random();
|
||||
|
||||
// Engine harmonics
|
||||
private readonly float[] _harmonicMultiples = { 1f, 2f, 3f, 4f };
|
||||
private readonly float[] _harmonicAmps = { 0.3f, 0.6f, 0.4f, 0.2f };
|
||||
private readonly float[] _harmonicPhases = new float[4];
|
||||
|
||||
public EngineSound()
|
||||
{
|
||||
Initialize(CHANNELS, SAMPLE_RATE);
|
||||
for (int i = 0; i < _harmonicPhases.Length; i++)
|
||||
_harmonicPhases[i] = (float)(_rand.NextDouble() * 2 * Math.PI);
|
||||
}
|
||||
|
||||
public void SetEngineState(float rpm, float throttle)
|
||||
{
|
||||
_currentRPM = rpm;
|
||||
_currentThrottle = throttle;
|
||||
_volume = 0.1f + 0.4f * throttle;
|
||||
}
|
||||
|
||||
public void StartSound()
|
||||
{
|
||||
if (!_isPlaying)
|
||||
{
|
||||
Play();
|
||||
_isPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void StopSound()
|
||||
{
|
||||
if (_isPlaying)
|
||||
{
|
||||
Stop();
|
||||
_isPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnGetData(out short[] samples)
|
||||
{
|
||||
int sampleCount = (int)(SAMPLE_RATE * BUFFER_DURATION) * CHANNELS;
|
||||
samples = new short[sampleCount];
|
||||
|
||||
for (int i = 0; i < sampleCount; i += 2)
|
||||
{
|
||||
float sampleValue = 0f;
|
||||
|
||||
// Read RPM per sample (instant)
|
||||
float rpm = _currentRPM;
|
||||
float throttle = _currentThrottle;
|
||||
|
||||
// Base frequency for 4-cylinder, 4-stroke
|
||||
float baseFreq = (rpm / 60f) * (_cylinders / 2f);
|
||||
|
||||
// Sum harmonics
|
||||
for (int h = 0; h < _harmonicMultiples.Length; h++)
|
||||
{
|
||||
float freq = baseFreq * _harmonicMultiples[h];
|
||||
float phaseInc = freq * 2f * MathF.PI / SAMPLE_RATE;
|
||||
|
||||
// Slight jitter for realism
|
||||
float jitter = 0.001f * ((float)_rand.NextDouble() - 0.5f);
|
||||
_harmonicPhases[h] += phaseInc + jitter;
|
||||
|
||||
if (_harmonicPhases[h] > 2f * MathF.PI)
|
||||
_harmonicPhases[h] -= 2f * MathF.PI;
|
||||
|
||||
sampleValue += MathF.Sin(_harmonicPhases[h]) * _harmonicAmps[h];
|
||||
}
|
||||
|
||||
// Add noise for roughness
|
||||
sampleValue += ((float)_rand.NextDouble() * 2f - 1f) * 0.02f * throttle;
|
||||
|
||||
// Volume and clamp
|
||||
sampleValue = Math.Clamp(sampleValue * _volume, -1f, 1f);
|
||||
short finalSample = (short)(sampleValue * 32767);
|
||||
|
||||
samples[i] = finalSample;
|
||||
samples[i + 1] = finalSample;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnSeek(Time timeOffset)
|
||||
{
|
||||
for (int i = 0; i < _harmonicPhases.Length; i++)
|
||||
_harmonicPhases[i] = (float)(_rand.NextDouble() * 2 * Math.PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user