■ WavWriter 구조체의 write_sample 메소드를 사용해 톱니파(sawtooth 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 |
use std::io; use std::fs; 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:/saw.wav", wav_spec ).unwrap(); let mut wave_vector : Vec<f32> = vec![]; let bpm : usize = 120; wave_vector.extend(get_sawtooth_wave_vector(60, calculate_note_length(bpm, 4), 0.5)); wave_vector.extend(get_sawtooth_wave_vector(64, calculate_note_length(bpm, 4), 0.5)); wave_vector.extend(get_sawtooth_wave_vector(67, calculate_note_length(bpm, 4), 0.5)); for v in wave_vector.into_iter() { wav_writer.write_sample(v).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 { let base_length : f32 = (60.0 / bpm as f32) * SAMPLE_RATE; return ((4.0 / note as f32) * base_length) as usize; } // scale : 음계, 예) 60(도), 64(미), 67(솔) // note_length : 음표 길이 (샘플 수) // gain : 출력 fn get_sawtooth_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]; for i in 0..note_length { let pif : f32 = (i as f32 / interval) % 1.0; wave_vector[i] = pif * 2.0 - 1.0; } return wave_vector.into_iter().map(|value : f32| (value * gain) as f32).collect(); } |