Skip to content

Instantly share code, notes, and snippets.

@sonota88
Last active September 9, 2025 10:57
Show Gist options
  • Select an option

  • Save sonota88/d93a37ff6b80bb290128f5d710eb7380 to your computer and use it in GitHub Desktop.

Select an option

Save sonota88/d93a37ff6b80bb290128f5d710eb7380 to your computer and use it in GitHub Desktop.
nes_noise
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()
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;
}
}
}
@sonota88
Copy link
Author

sonota88 commented Sep 7, 2025

Rubyでファミコンのノイズ音を作ってみた
https://qiita.com/sonota88/items/d2c7d91d7058cda63e82

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment