Last active
September 9, 2025 10:57
-
-
Save sonota88/d93a37ff6b80bb290128f5d710eb7380 to your computer and use it in GitHub Desktop.
nes_noise
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule Context do | |
| defstruct noise_timer: nil, | |
| period: nil, | |
| shift_register: <<0b000_0000_0000_0001::size(15)>> | |
| end | |
| defmodule NesNoise do | |
| import Bitwise | |
| defp master_clock_hz, do: 236_250_000.0 / 11 | |
| defp cpu_clock_hz, do: master_clock_hz() / 12 # 1_789_772.7272727273 | |
| defp period_table do | |
| [4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068] | |
| end | |
| defp shift(shift_register) do | |
| <<_::13, b1::1, b0::1>> = shift_register | |
| next_bit = bxor(b1, b0) | |
| <<next_tail::14, _::1>> = shift_register | |
| {<<next_bit::1, next_tail::14>>, b1} | |
| end | |
| defp nes_noise(n, ctx) do | |
| if n == 0 do | |
| ; | |
| else | |
| {next_shift_register, bit0} = | |
| if ctx.noise_timer == 0 do | |
| shift(ctx.shift_register) | |
| else | |
| {ctx.shift_register, nil} | |
| end | |
| if bit0 do | |
| IO.puts bit0 * 2 - 1 | |
| end | |
| next_noise_timer = | |
| if ctx.noise_timer == 0 do | |
| ctx.period | |
| else | |
| ctx.noise_timer - 1 | |
| end | |
| nes_noise( | |
| n - 1, | |
| %{ | |
| ctx | | |
| shift_register: next_shift_register, | |
| noise_timer: next_noise_timer | |
| } | |
| ) | |
| end | |
| end | |
| def main do | |
| reg400e_period = System.argv() |> Enum.at(0) |> String.to_integer | |
| duration_sec = 1.0 | |
| num_cpu_cycles = cpu_clock_hz() * duration_sec |> floor | |
| IO.puts(:stderr, "num_cpu_cycles (#{num_cpu_cycles})") | |
| period = period_table() |> Enum.at(reg400e_period) | |
| ctx = %Context{ | |
| noise_timer: period, | |
| period: period | |
| } | |
| IO.puts cpu_clock_hz() / (period + 1) | |
| nes_noise(num_cpu_cycles, ctx) | |
| end | |
| end | |
| NesNoise.main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::env; | |
| const MASTER_CLOCK_HZ: f64 = 236_250_000.0 / 11.0; | |
| const CPU_CLOCK_HZ: f64 = MASTER_CLOCK_HZ / 12.0; | |
| const PERIOD_TABLE: [i32; 16] = [ | |
| 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068 | |
| ]; | |
| struct Noise { | |
| timer: i32, | |
| shift_reg: u16, | |
| } | |
| impl Noise { | |
| fn new() -> Noise { | |
| Noise { | |
| timer: PERIOD_TABLE[0], | |
| shift_reg: 0b0000_0000_0000_0001, | |
| } | |
| } | |
| fn shift_reg_bit(&self, i: usize) -> u16 { | |
| (self.shift_reg >> i) & 0b0000_0000_0000_0001 | |
| } | |
| fn update_shift_reg(&mut self) { | |
| let next_bit = self.shift_reg_bit(1) ^ self.shift_reg_bit(0); | |
| self.shift_reg = self.shift_reg >> 1; | |
| if next_bit == 1 { | |
| self.shift_reg = self.shift_reg | 0b0100_0000_0000_0000 | |
| } | |
| } | |
| } | |
| fn main() { | |
| let args: Vec<String> = env::args().collect(); | |
| let reg400e_period = args[1].parse::<usize>().unwrap(); | |
| let period = PERIOD_TABLE[reg400e_period]; | |
| let mut noise = Noise::new(); | |
| let duration_sec = 1.0; | |
| let num_cpu_cycles = (CPU_CLOCK_HZ / duration_sec).floor() as u32; | |
| let raw_sampling_rate = CPU_CLOCK_HZ / ((period + 1) as f64); | |
| println!("{}", raw_sampling_rate); | |
| for _ in 0..num_cpu_cycles { | |
| if noise.timer == 0 { | |
| noise.timer = period; | |
| noise.update_shift_reg(); | |
| let bit0 = noise.shift_reg_bit(0) as i32; | |
| println!("{}", bit0 * 2 - 1); | |
| } else { | |
| noise.timer -= 1; | |
| } | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Rubyでファミコンのノイズ音を作ってみた
https://qiita.com/sonota88/items/d2c7d91d7058cda63e82