■ WavWriter 구조체의 write_sample 메소드를 사용해 펄스파(pulse wave)의 WAV 파일을 생성하는 방법을 보여준다.
▶ Cargo.toml
1 2 3 4 5 6 7 8 9 |
[package] name = "test_project" version = "0.1.0" edition = "2021" [dependencies] hound = "3.4.0" |
▶ src/main.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
use std::fs; use std::io; use hound; const SAMPLE_RATE : f32 = 44100.0; fn main() { let wav_spec : hound::WavSpec = hound::WavSpec { channels : 1, sample_rate : SAMPLE_RATE as u32, bits_per_sample : 32, sample_format : hound::SampleFormat::Float }; let mut wav_writer : hound::WavWriter<io::BufWriter<fs::File>> = hound::WavWriter::create("d:/pulse.wav", wav_spec).unwrap(); let mut wave_vector : Vec<f32> = vec![]; let bpm : usize = 120; [0.3, 0.1, 0.7, 0.5].iter().for_each ( |duty : &f32| { [60, 64, 67, 72].iter().for_each ( |scale : &i32| { wave_vector.extend(get_pulse_wave_vector(*scale, calculate_note_length(bpm, 4), 0.5, *duty)); } ); } ); for value in wave_vector.into_iter() { wav_writer.write_sample(value).unwrap(); } } // scale : 음계, 예) 60(도), 64(미), 67(솔) fn get_frequency(scale : i32) -> f32 { return 440.0 * 2.0f32.powf((scale - 69) as f32 / 12.0); } // bpm : 분당 박자, beats per minute // note : 음표 예) 4(4분 음표) fn calculate_note_length(bpm : usize, note : usize) -> usize { return ((4.0 / note as f32) * (60.0 / bpm as f32) * SAMPLE_RATE) as usize; } // scale : 음계, 예) 60(도), 64(미), 67(솔) // note_length : 음표 길이 (샘플 수) // gain : 출력 // duty : 듀티 fn get_pulse_wave_vector(scale : i32, note_length : usize, gain : f32, duty : f32) -> Vec<f32> { let frequency : f32 = get_frequency(scale); let interval : f32 = SAMPLE_RATE / frequency; let mut wave_vector : Vec<f32> = vec![0.0; note_length]; for i in 0..note_length { let saw : f32 = (i as f32 / interval) % 1.0; wave_vector[i] = if saw > duty { -1.0 } else { 1.0 }; } return wave_vector.into_iter().map(|v: f32| (v * gain) as f32).collect(); } |