LoginSignup
7
4

More than 1 year has passed since last update.

夏休みの自由研究「RustでCR戦姫絶唱シンフォギアの大当たりの音を作る」

Posted at

本記事について

仕事もひと段落し、Rustの勉強中にRustでサウンドが作れるということで、以前からやってみたかった夏休みの自由研究
「戦姫絶唱シンフォギアが永遠に当たる気分を作る」というテーマでやってみました。

参考動画

こちらの二つを掛け合わせてできました。

とても楽しかったです。

補足

シンフォギアライブ当選された方おめでとうございます!!

是非とも11月20日はみなさんの「絶唱」楽しみにしております。

うらやましいなぁ。。。

ソースコード

このコードに関する解説はぜひ本をお買い求めください。

追加のクレート

hound = "3.4.0"

main.rs

use hound;
const SAMPLE_RATE: f32 = 44100.0;

fn main() {
    let spec = hound::WavSpec {
        channels: 1,
        sample_rate: SAMPLE_RATE as u32,
        bits_per_sample: 32,
        sample_format: hound::SampleFormat::Float,
    };
    let mut fw = hound::WavWriter::create("saw.wav", spec).unwrap();
    let mut wav: Vec<f32> = vec![];
    let bpm = 120;
    wav.extend(sawtooth_wave(67, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(74, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(75, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(75, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(75, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(75, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(75, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(67, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(67, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(67, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(67, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(67, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(67, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(74, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(74, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(74, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(74, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(74, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(74, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(70, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(70, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(70, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(70, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(70, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(70, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 16), 0.4));
    wav.extend(sawtooth_wave(72, calc_len(bpm, 4), 0.4));

    for v in wav.into_iter() {
        fw.write_sample(v).unwrap();
        println!("{}", v);
    }
}

fn noteno_to_hz(no: i32) -> f32 {
    440.0 * 2.0f32.powf((no - 69) as f32 / 12.0)
}

fn calc_len(bpm: usize, n: usize) -> usize {
    let base_len = (60.0 / bpm as f32) * SAMPLE_RATE;
    ((4.0 / n as f32) * base_len) as usize
}

fn sawtooth_wave(noteno: i32, len: usize, gain: f32) -> Vec<f32> {
    let tone = noteno_to_hz(noteno);
    let form_samples = SAMPLE_RATE / tone;
    let mut wav: Vec<f32> = vec![0.0; len];
    for i in 0..len {
        let pif = (i as f32 / form_samples) % 1.0;
        wav[i] = pif * 2.0 - 1.0;
    }
    wav.into_iter().map(|v| (v * gain) as f32).collect()
}

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4