Generate a multi-frequency audio::Sample with broadband noise floor. Models a MEMS mic (INMP441): self-noise adds continuous energy to all audio::fft::FFT bins. noiseAmp is the peak amplitude of the white noise. Uses deterministic PRNG seeded from timestamp for reproducibility.
| 54 | // audio::fft::FFT bins. noiseAmp is the peak amplitude of the white noise. |
| 55 | // Uses deterministic PRNG seeded from timestamp for reproducibility. |
| 56 | audio::Sample makeMixWithNoise(float bassAmp, float midAmp, float trebAmp, |
| 57 | float noiseAmp, u32 timestamp, |
| 58 | int count = 512, |
| 59 | float sampleRate = 44100.0f) { |
| 60 | vector<i16> data(count, 0); |
| 61 | const float freqs[3] = {200.0f, 5000.0f, 9000.0f}; |
| 62 | const float amps[3] = {bassAmp, midAmp, trebAmp}; |
| 63 | |
| 64 | // Add tonal content |
| 65 | for (int band = 0; band < 3; ++band) { |
| 66 | for (int i = 0; i < count; ++i) { |
| 67 | float phase = 2.0f * FL_M_PI * freqs[band] * i / sampleRate; |
| 68 | float sample = amps[band] * fl::sinf(phase); |
| 69 | data[i] = clampI16(static_cast<float>(data[i]) + sample); |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | // Add broadband white noise (deterministic per-timestamp) |
| 74 | fl_random rng(static_cast<u16>(timestamp * 7 + 31)); |
| 75 | for (int i = 0; i < count; ++i) { |
| 76 | // Map u16 [0, 65535] to float [-1, 1] |
| 77 | float noise = (static_cast<float>(rng.random16()) / 32767.5f) - 1.0f; |
| 78 | data[i] = clampI16(static_cast<float>(data[i]) + noiseAmp * noise); |
| 79 | } |
| 80 | return audio::Sample(data, timestamp); |
| 81 | } |
| 82 | |
| 83 | // Generate a sample with spectral leakage: a bass tone near the mid band |
| 84 | // boundary (3500 Hz — just below the 3688 Hz boundary) plus actual mid |
no test coverage detected