Quantcast
Viewing latest article 3
Browse Latest Browse All 746

C# Code for Synthesizing Nes Noise: The result is different from the real Nes noise!

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.

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



Viewing latest article 3
Browse Latest Browse All 746

Trending Articles