This is a C# code for synthesizing the noise of Nintendo consoles.
First, it generates 16 audio segments with frequency variations in non - short mode, each lasting 0.5 seconds.
Then, it generates another 16 audio segments with frequency variations in short mode, also each lasting 0.5 seconds.
Finally, the audio arrays are put into a player for playback, with a sampling rate of 44100 Hz.
The current problem is that there is a certain gap between the generated audio and the real NES noise.
Specifically, the high - frequency sounds are not very similar, while the low - frequency sounds are relatively close.
Please help me analyze and modify this code.
I want the generated noise to perfectly approximate the NES noise.
First, it generates 16 audio segments with frequency variations in non - short mode, each lasting 0.5 seconds.
Then, it generates another 16 audio segments with frequency variations in short mode, also each lasting 0.5 seconds.
Finally, the audio arrays are put into a player for playback, with a sampling rate of 44100 Hz.
The current problem is that there is a certain gap between the generated audio and the real NES noise.
Specifically, the high - frequency sounds are not very similar, while the low - frequency sounds are relatively close.
Please help me analyze and modify this code.
I want the generated noise to perfectly approximate the NES noise.
Code:
using System;using System.IO;using System.Media;using System.Collections.Generic;public class NoiseGenerator{ // Noise period table (NTSC non - short mode) private static readonly ushort[] NoisePeriodsNTSC = { 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068 }; private const double NTSCBaseFreq = 1789773.0; // Core algorithm for generating noise private static short[] GenerateNoiseSegment(int index, bool shortMode, double durationSec, int sampleRate) { int period = NoisePeriodsNTSC[index]; int samples = (int)(durationSec * sampleRate); short[] buffer = new short[samples]; ushort shiftReg = 1; int sampleRateMode = shortMode ? 8 : 13; // Accurate period calculation (based on APU clock) double clockRate = NTSCBaseFreq; // 1.789773 MHz // Correct frequency calculation, considering the impact of sampleRateMode on frequency double cyclesPerSample = clockRate / sampleRate / (sampleRateMode == 8 ? 2 : 1); double noiseCycles = 0; for (int i = 0; i < samples; i++) { int cyclesToRun = (int)(cyclesPerSample + noiseCycles); noiseCycles = (cyclesPerSample + noiseCycles) - cyclesToRun; while (cyclesToRun-- > 0) { if (--period <= 0) { period = NoisePeriodsNTSC[index]; ushort bit14 = (ushort)((shiftReg << 14) & 0x4000); ushort bitSR = (ushort)((shiftReg << sampleRateMode) & 0x7FFF); ushort newBit = (ushort)((bit14 ^ bitSR) & 0x4000); shiftReg = (ushort)((newBit | (shiftReg >> 1)) & 0x7FFF); } } buffer[i] = (short)((shiftReg & 1) != 0 ? 5000 : -5000); } return buffer; } // Generate the WAV file header private static byte[] CreateWavHeader(int dataSize, int sampleRate) { using (MemoryStream ms = new MemoryStream()) using (BinaryWriter writer = new BinaryWriter(ms)) { writer.Write("RIFF".ToCharArray()); writer.Write(36 + dataSize); // Total file size writer.Write("WAVEfmt ".ToCharArray()); writer.Write(16); // fmt chunk size writer.Write((ushort)1); // PCM format writer.Write((ushort)1); // Mono channel writer.Write(sampleRate); // Sample rate writer.Write(sampleRate * 2); // Byte rate writer.Write((ushort)2); // Block alignment writer.Write((ushort)16); // Bit depth writer.Write("data".ToCharArray()); writer.Write(dataSize); // Data size return ms.ToArray(); } } public static void Main() { const int sampleRate = 44100; const double duration = 0.5; List<short[]> noiseSegments = new List<short[]>(); // Generate 16 frequencies in non - short mode (13 - bit shift) for (int i = 0; i < NoisePeriodsNTSC.Length; i++) { noiseSegments.Add(GenerateNoiseSegment(i, false, duration, sampleRate)); } // Generate 16 frequencies in short mode (8 - bit shift) (using the same period table) for (int i = 0; i < NoisePeriodsNTSC.Length; i++) { noiseSegments.Add(GenerateNoiseSegment(i, true, duration, sampleRate)); } // Merge all audio data List<short> fullAudio = new List<short>(); foreach (var segment in noiseSegments) { fullAudio.AddRange(segment); } // Generate the WAV file byte[] pcmBytes = new byte[fullAudio.Count * 2]; Buffer.BlockCopy(fullAudio.ToArray(), 0, pcmBytes, 0, pcmBytes.Length); byte[] wavHeader = CreateWavHeader(pcmBytes.Length, sampleRate); using (MemoryStream wavStream = new MemoryStream()) { wavStream.Write(wavHeader, 0, wavHeader.Length); wavStream.Write(pcmBytes, 0, pcmBytes.Length); wavStream.Position = 0; new SoundPlayer(wavStream).PlaySync(); } }}
Statistics: Posted by icendragon — Thu Feb 06, 2025 11:55 pm — Replies 4 — Views 350