■ WavWriter 구조체의 write_sample 메소드를 사용해 삼각파(triangle 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 80 |
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:/tri.wav", wav_spec).unwrap(); let mut wave_vector : Vec<f32> = vec![]; let bpm : usize = 120; [60, 64, 67, 64, 60, 64, 67, 72].iter().for_each ( |scale: &i32| { wave_vector.extend(get_triangle_wave_vector(*scale, calculate_note_length(bpm, 8), 0.5)); } ); for wave in wave_vector.into_iter() { wav_writer.write_sample(wave).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 : 출력 fn get_triangle_wave_vector(scale : i32, note_length : usize, gain : 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]; let half_interval : f32 = interval / 2.0; for i in 0..note_length { let temporary_value : f32 = i as f32 / half_interval; let mut value : f32 = 2.0 * (temporary_value % 1.0) - 1.0; let is_climbing : bool = temporary_value.floor() as usize % 2 == 0; value = if is_climbing { value } else { -value }; wave_vector[i] = value; } return wave_vector.into_iter().map(|value : f32| (value * gain) as f32).collect(); } |