├── .gitignore ├── README.md └── sound_programming ├── Cargo.toml ├── drum.wav ├── ex10_1.wav ├── ex10_2.wav ├── ex10_3.wav ├── ex10_4.wav ├── ex10_5.wav ├── ex10_6.wav ├── ex11_1.wav ├── ex11_2.wav ├── ex11_3.wav ├── ex11_4.wav ├── ex11_5.wav ├── ex11_6.wav ├── ex11_7_pcm.wav ├── ex11_8_pcm.wav ├── ex11_9_pcm.wav ├── ex11_sine_500hz.wav ├── ex1_1_8bit.wav ├── ex1_1_a.wav ├── ex1_1_b.wav ├── ex1_1_c.wav ├── ex1_2_8bit.wav ├── ex1_2_a.wav ├── ex1_2_b.wav ├── ex1_2_c.wav ├── ex2_1.wav ├── ex2_2.wav ├── ex3_1.wav ├── ex3_2.wav ├── ex3_3.wav ├── ex3_4.wav ├── ex3_5.wav ├── ex4_4a.wav ├── ex4_4b.wav ├── ex5_1.wav ├── ex5_2.wav ├── ex5_3.wav ├── ex5_4.wav ├── ex5_5.wav ├── ex6_1.wav ├── ex6_2.wav ├── ex6_3.wav ├── ex6_4.wav ├── ex6_5.wav ├── ex7_1.wav ├── ex7_1_pulse_train.wav ├── ex7_2.wav ├── ex7_3.wav ├── ex7_3_pulse_train.wav ├── ex7_4.wav ├── ex8_1.wav ├── ex8_10.wav ├── ex8_11.wav ├── ex8_12.wav ├── ex8_2.wav ├── ex8_3.wav ├── ex8_4.wav ├── ex8_5.wav ├── ex8_6.wav ├── ex8_7.wav ├── ex8_8.wav ├── ex8_9.wav ├── ex9_1.wav ├── ex9_10.wav ├── ex9_11.wav ├── ex9_2.wav ├── ex9_3.wav ├── ex9_4.wav ├── ex9_5.wav ├── ex9_6.wav ├── ex9_7.wav ├── ex9_8.wav ├── ex9_9.wav ├── ima_adpcm.wav ├── pcma.wav ├── pcmu.wav ├── response.wav ├── sine_1000hz.wav ├── sine_1s.wav ├── sine_2s.wav ├── sine_500hz.wav ├── sine_500hz_3500hz.wav ├── src ├── first.rs ├── lib.rs ├── main.rs ├── second.rs └── third.rs ├── synth.wav ├── vocal.wav ├── wave_utils ├── Cargo.toml └── src │ ├── fft.rs │ ├── filter.rs │ ├── lib.rs │ └── wave │ ├── mod.rs │ ├── read.rs │ └── write.rs └── white_noise.wav /.gitignore: -------------------------------------------------------------------------------- 1 | sound_programming_c/ 2 | sound_programming/target/ 3 | sound_programming/wave_utils/target/ 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sound_programming_rust 2 | [「サウンドプログラミング入門――音響合成の基本とC言語による実装」](https://www.amazon.co.jp/dp/4774155225)のサンプルプログラムRustへの移植 3 | 4 | ## 内容 5 | [著者様が配布されているサンプルプログラム](http://floor13.sakura.ne.jp/book06/book06.html)をRustに勝手に移植してみる。ライブラリとしての使用が意図されていると思われる `wave.h` (67回登場。テスト済、未移植), `sinc.h` (12回登場。テスト済、移植済), `iir_filter.h` (10回登場。テスト済、移植済), `adsr.h`(8回登場。テスト済、移植済), `window_function.h` (7回登場。テスト済、移植済), `fft.h` (4回登場。テスト済、移植済), `fir_filter.h` (4回登場。テスト済、移植済) を移植するとともに、サンプルプログラムも全て移植し、(乱数が登場するもの以外に関しては)元ファイルとmd5が一致することを目標とする。 6 | 12章については、Windowsに依存し面倒であるため移植を行わない。 7 | なお、作者様に連絡が取れていないため、何かあったら公開を停止する。 8 | 9 | 元のCのソースは上記の[配布元](http://floor13.sakura.ne.jp/book06/book06.html)を参照のこと。 10 | 11 | ## 現状 12 | 13 | * 2018/05/21 ライブラリ含め完全移植完了 14 | * 2018/05/20 11章までのサンプルの移植が完了。12章は移植しないためこれにて移植完了。 15 | * 2018/05/19 10章までのサンプルの移植が完了 16 | * 2018/05/19 9章までのサンプルの移植が完了 17 | * 2018/05/17 8章までのサンプルの移植が完了 18 | * 2018/05/16 7章までのサンプルの移植が完了 19 | * 2018/05/16 fir_filter.cの完全移植が完了 20 | * 2018/05/16 iir_filter.cの完全移植が完了 21 | * 2018/05/16 6章までのサンプルの移植が完了 22 | * 2018/05/16 5章までのサンプルの移植が完了 23 | * 2018/05/16 fft.cの完全移植が完了 24 | * 2018/05/16 4章までのサンプルの移植が完了 25 | * 2018/05/16 adsr.cの完全移植が完了 26 | * 2018/05/15 3章までのサンプルの移植が完了 27 | * 2018/05/15 window_function.cの完全移植が完了 28 | * 2018/05/15 sinc.cの完全移植が完了 29 | 30 | -------------------------------------------------------------------------------- /sound_programming/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sound_programming" 3 | version = "0.1.0" 4 | authors = ["hsjoihs "] 5 | 6 | [dependencies] 7 | rand = "0.4.0" 8 | num-complex = "0.1" 9 | wave_utils = { path = "wave_utils" } 10 | 11 | -------------------------------------------------------------------------------- /sound_programming/drum.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/drum.wav -------------------------------------------------------------------------------- /sound_programming/ex10_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex10_1.wav -------------------------------------------------------------------------------- /sound_programming/ex10_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex10_2.wav -------------------------------------------------------------------------------- /sound_programming/ex10_3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex10_3.wav -------------------------------------------------------------------------------- /sound_programming/ex10_4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex10_4.wav -------------------------------------------------------------------------------- /sound_programming/ex10_5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex10_5.wav -------------------------------------------------------------------------------- /sound_programming/ex10_6.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex10_6.wav -------------------------------------------------------------------------------- /sound_programming/ex11_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_1.wav -------------------------------------------------------------------------------- /sound_programming/ex11_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_2.wav -------------------------------------------------------------------------------- /sound_programming/ex11_3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_3.wav -------------------------------------------------------------------------------- /sound_programming/ex11_4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_4.wav -------------------------------------------------------------------------------- /sound_programming/ex11_5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_5.wav -------------------------------------------------------------------------------- /sound_programming/ex11_6.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_6.wav -------------------------------------------------------------------------------- /sound_programming/ex11_7_pcm.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_7_pcm.wav -------------------------------------------------------------------------------- /sound_programming/ex11_8_pcm.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_8_pcm.wav -------------------------------------------------------------------------------- /sound_programming/ex11_9_pcm.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_9_pcm.wav -------------------------------------------------------------------------------- /sound_programming/ex11_sine_500hz.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex11_sine_500hz.wav -------------------------------------------------------------------------------- /sound_programming/ex1_1_8bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex1_1_8bit.wav -------------------------------------------------------------------------------- /sound_programming/ex1_1_a.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex1_1_a.wav -------------------------------------------------------------------------------- /sound_programming/ex1_1_b.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex1_1_b.wav -------------------------------------------------------------------------------- /sound_programming/ex1_1_c.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex1_1_c.wav -------------------------------------------------------------------------------- /sound_programming/ex1_2_8bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex1_2_8bit.wav -------------------------------------------------------------------------------- /sound_programming/ex1_2_a.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex1_2_a.wav -------------------------------------------------------------------------------- /sound_programming/ex1_2_b.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex1_2_b.wav -------------------------------------------------------------------------------- /sound_programming/ex1_2_c.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex1_2_c.wav -------------------------------------------------------------------------------- /sound_programming/ex2_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex2_1.wav -------------------------------------------------------------------------------- /sound_programming/ex2_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex2_2.wav -------------------------------------------------------------------------------- /sound_programming/ex3_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex3_1.wav -------------------------------------------------------------------------------- /sound_programming/ex3_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex3_2.wav -------------------------------------------------------------------------------- /sound_programming/ex3_3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex3_3.wav -------------------------------------------------------------------------------- /sound_programming/ex3_4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex3_4.wav -------------------------------------------------------------------------------- /sound_programming/ex3_5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex3_5.wav -------------------------------------------------------------------------------- /sound_programming/ex4_4a.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex4_4a.wav -------------------------------------------------------------------------------- /sound_programming/ex4_4b.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex4_4b.wav -------------------------------------------------------------------------------- /sound_programming/ex5_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex5_1.wav -------------------------------------------------------------------------------- /sound_programming/ex5_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex5_2.wav -------------------------------------------------------------------------------- /sound_programming/ex5_3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex5_3.wav -------------------------------------------------------------------------------- /sound_programming/ex5_4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex5_4.wav -------------------------------------------------------------------------------- /sound_programming/ex5_5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex5_5.wav -------------------------------------------------------------------------------- /sound_programming/ex6_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex6_1.wav -------------------------------------------------------------------------------- /sound_programming/ex6_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex6_2.wav -------------------------------------------------------------------------------- /sound_programming/ex6_3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex6_3.wav -------------------------------------------------------------------------------- /sound_programming/ex6_4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex6_4.wav -------------------------------------------------------------------------------- /sound_programming/ex6_5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex6_5.wav -------------------------------------------------------------------------------- /sound_programming/ex7_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex7_1.wav -------------------------------------------------------------------------------- /sound_programming/ex7_1_pulse_train.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex7_1_pulse_train.wav -------------------------------------------------------------------------------- /sound_programming/ex7_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex7_2.wav -------------------------------------------------------------------------------- /sound_programming/ex7_3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex7_3.wav -------------------------------------------------------------------------------- /sound_programming/ex7_3_pulse_train.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex7_3_pulse_train.wav -------------------------------------------------------------------------------- /sound_programming/ex7_4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex7_4.wav -------------------------------------------------------------------------------- /sound_programming/ex8_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_1.wav -------------------------------------------------------------------------------- /sound_programming/ex8_10.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_10.wav -------------------------------------------------------------------------------- /sound_programming/ex8_11.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_11.wav -------------------------------------------------------------------------------- /sound_programming/ex8_12.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_12.wav -------------------------------------------------------------------------------- /sound_programming/ex8_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_2.wav -------------------------------------------------------------------------------- /sound_programming/ex8_3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_3.wav -------------------------------------------------------------------------------- /sound_programming/ex8_4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_4.wav -------------------------------------------------------------------------------- /sound_programming/ex8_5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_5.wav -------------------------------------------------------------------------------- /sound_programming/ex8_6.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_6.wav -------------------------------------------------------------------------------- /sound_programming/ex8_7.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_7.wav -------------------------------------------------------------------------------- /sound_programming/ex8_8.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_8.wav -------------------------------------------------------------------------------- /sound_programming/ex8_9.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex8_9.wav -------------------------------------------------------------------------------- /sound_programming/ex9_1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_1.wav -------------------------------------------------------------------------------- /sound_programming/ex9_10.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_10.wav -------------------------------------------------------------------------------- /sound_programming/ex9_11.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_11.wav -------------------------------------------------------------------------------- /sound_programming/ex9_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_2.wav -------------------------------------------------------------------------------- /sound_programming/ex9_3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_3.wav -------------------------------------------------------------------------------- /sound_programming/ex9_4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_4.wav -------------------------------------------------------------------------------- /sound_programming/ex9_5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_5.wav -------------------------------------------------------------------------------- /sound_programming/ex9_6.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_6.wav -------------------------------------------------------------------------------- /sound_programming/ex9_7.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_7.wav -------------------------------------------------------------------------------- /sound_programming/ex9_8.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_8.wav -------------------------------------------------------------------------------- /sound_programming/ex9_9.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ex9_9.wav -------------------------------------------------------------------------------- /sound_programming/ima_adpcm.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/ima_adpcm.wav -------------------------------------------------------------------------------- /sound_programming/pcma.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/pcma.wav -------------------------------------------------------------------------------- /sound_programming/pcmu.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/pcmu.wav -------------------------------------------------------------------------------- /sound_programming/response.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/response.wav -------------------------------------------------------------------------------- /sound_programming/sine_1000hz.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/sine_1000hz.wav -------------------------------------------------------------------------------- /sound_programming/sine_1s.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/sine_1s.wav -------------------------------------------------------------------------------- /sound_programming/sine_2s.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/sine_2s.wav -------------------------------------------------------------------------------- /sound_programming/sine_500hz.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/sine_500hz.wav -------------------------------------------------------------------------------- /sound_programming/sine_500hz_3500hz.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/sine_500hz_3500hz.wav -------------------------------------------------------------------------------- /sound_programming/src/first.rs: -------------------------------------------------------------------------------- 1 | extern crate rand; 2 | use num_complex::Complex; 3 | use rand::Rng; 4 | use sine_wave; 5 | use std::f64::consts::PI; 6 | use wave_utils::create_Hanning_window; 7 | use wave_utils::determine_J; 8 | use wave_utils::fft::safe_FFT_; 9 | use wave_utils::fft::safe_IFFT_; 10 | use wave_utils::filter::get_FIR_LPF; 11 | use wave_utils::filter::safe_FIR_filtering; 12 | use wave_utils::filter::safe_IIR_LPF; 13 | use wave_utils::filter::safe_IIR_filtering; 14 | use wave_utils::linear; 15 | use wave_utils::mult; 16 | use wave_utils::wave::wave_read_16bit_mono_safer3; 17 | use wave_utils::wave::wave_read_16bit_stereo_safer3; 18 | use wave_utils::wave::wave_write_16bit_mono_safer3; 19 | use wave_utils::wave::wave_write_16bit_stereo_safer3; 20 | use wave_utils::MonoPcm; 21 | 22 | #[allow(non_snake_case)] 23 | fn verify_(X: &[Complex]) { 24 | /* 周波数特性 */ 25 | for (k, item) in X.iter().enumerate() { 26 | assert_close(item.re, 0.0); 27 | assert_close( 28 | item.im, 29 | match k { 30 | 4 => -16.0, 31 | 60 => 16.0, 32 | _ => 0.0, 33 | }, 34 | ); 35 | } 36 | } 37 | 38 | fn exponential_decay( 39 | pcm_fs: usize, 40 | amplitude: f64, 41 | decay_factor: f64, 42 | decay_time: f64, 43 | length: usize, 44 | ) -> Vec { 45 | (0..length) 46 | .map(|n| amplitude * (-decay_factor * n as f64 / (pcm_fs as f64 * decay_time)).exp()) 47 | .collect() 48 | } 49 | 50 | #[allow(non_snake_case)] 51 | fn dft(N: usize, func: &dyn Fn(usize) -> f64) -> Vec> { 52 | let mut x: Vec> = vec![Complex::new(0.0, 0.0); N]; 53 | let mut X: Vec> = vec![Complex::new(0.0, 0.0); N]; 54 | 55 | let pcm_slice = wave_read_16bit_mono_safer3("sine_500hz.wav").s; 56 | 57 | /* 波形 */ 58 | for n in 0..N { 59 | x[n] = Complex::new(pcm_slice[n] * func(n) /* x(n)の実数部 */, 0.0); /* x(n)の虚数部 */ 60 | } 61 | 62 | /* DFT */ 63 | for k_ in 0..N { 64 | let k = k_ as f64; 65 | for n_ in 0..N { 66 | let n = n_ as f64; 67 | let N = N as f64; 68 | let W = Complex::new(0.0, -(2.0 * PI * k * n / N)).exp(); 69 | X[k_] += W * x[n_]; 70 | } 71 | } 72 | 73 | X 74 | } 75 | 76 | fn assert_close(a: f64, b: f64) { 77 | assert!((a - b).abs() < 1.75e-4); 78 | } 79 | 80 | pub fn first() { 81 | ex1_1(); 82 | ex1_2(); 83 | ex2_1(); 84 | ex2_2(); 85 | ex3_1(); 86 | ex3_2(); 87 | ex3_3(); 88 | ex3_4(); 89 | if false { 90 | ex3_5(); // slow and random 91 | } 92 | ex4_1(); 93 | ex4_2(); 94 | ex4_3(); 95 | ex4_4(); 96 | ex5_1(); 97 | ex5_2(); 98 | ex5_3(); 99 | ex5_4(); 100 | ex5_5(); 101 | ex6_1(); 102 | ex6_2(); 103 | ex6_3(); 104 | ex6_4(); 105 | if false { 106 | ex6_5(); // slooooow 107 | } 108 | } 109 | 110 | fn ex1_1() { 111 | let pcm0 = wave_read_16bit_mono_safer3("ex1_1_a.wav"); /* 音データの入力 */ 112 | let pcm1 = pcm0; /* 音データのムーブ */ 113 | 114 | wave_write_16bit_mono_safer3("ex1_1_b.wav", &pcm1); /* 音データの出力 */ 115 | } 116 | 117 | #[allow(non_snake_case)] 118 | fn ex1_2() { 119 | let pcm0 = wave_read_16bit_stereo_safer3("ex1_2_a.wav"); 120 | let pcm1 = pcm0; /* 音データのムーブ */ 121 | 122 | wave_write_16bit_stereo_safer3("ex1_2_b.wav", &pcm1); 123 | } 124 | 125 | fn ex2_1() { 126 | let pcm_fs: usize = 44100; /* 標本化周波数 */ 127 | let pcm_length: usize = pcm_fs * 1; /* 音データの長さ */ 128 | 129 | /* サイン波 */ 130 | let pcm = MonoPcm::new16_fn( 131 | pcm_fs, 132 | pcm_length, 133 | Box::new(move |n| { 134 | let a = 0.1; /* 振幅 */ 135 | let f0 = 500.0; /* 周波数 */ 136 | a * (2.0 * PI * f0 * (n as f64) / (pcm_fs as f64)).sin() 137 | }), 138 | ); 139 | 140 | wave_write_16bit_mono_safer3("ex2_1.wav", &pcm); 141 | } 142 | 143 | fn ex2_2() { 144 | let pcm_fs: usize = 44100; /* 標本化周波数 */ 145 | let pcm_length: usize = pcm_fs * 2; /* 音データの長さ */ 146 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 147 | 148 | sine_wave( 149 | &mut pcm, 150 | 261.63, 151 | 0.1, 152 | mult(pcm_fs, 0.00), 153 | mult(pcm_fs, 0.25), 154 | ); /* C4 */ 155 | sine_wave( 156 | &mut pcm, 157 | 293.66, 158 | 0.1, 159 | mult(pcm_fs, 0.25), 160 | mult(pcm_fs, 0.25), 161 | ); /* D4 */ 162 | sine_wave( 163 | &mut pcm, 164 | 329.63, 165 | 0.1, 166 | mult(pcm_fs, 0.50), 167 | mult(pcm_fs, 0.25), 168 | ); /* E4 */ 169 | sine_wave( 170 | &mut pcm, 171 | 349.23, 172 | 0.1, 173 | mult(pcm_fs, 0.75), 174 | mult(pcm_fs, 0.25), 175 | ); /* F4 */ 176 | sine_wave( 177 | &mut pcm, 178 | 392.00, 179 | 0.1, 180 | mult(pcm_fs, 1.00), 181 | mult(pcm_fs, 0.25), 182 | ); /* G4 */ 183 | sine_wave( 184 | &mut pcm, 185 | 440.00, 186 | 0.1, 187 | mult(pcm_fs, 1.25), 188 | mult(pcm_fs, 0.25), 189 | ); /* A4 */ 190 | sine_wave( 191 | &mut pcm, 192 | 493.88, 193 | 0.1, 194 | mult(pcm_fs, 1.50), 195 | mult(pcm_fs, 0.25), 196 | ); /* B4 */ 197 | sine_wave( 198 | &mut pcm, 199 | 523.25, 200 | 0.1, 201 | mult(pcm_fs, 1.75), 202 | mult(pcm_fs, 0.25), 203 | ); /* C5 */ 204 | 205 | wave_write_16bit_mono_safer3("ex2_2.wav", &pcm); 206 | } 207 | 208 | fn ex3_1() { 209 | let f0 = 500.0; /* 基本周波数 */ 210 | 211 | let pcm_fs = 44100; 212 | let pcm_length = pcm_fs * 1; 213 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 214 | 215 | /* ノコギリ波 */ 216 | for i_ in 1..=44 { 217 | let i = i_ as f64; 218 | for (n, item) in pcm.s.iter_mut().enumerate() { 219 | *item += 1.0 / i * (2.0 * PI * i * f0 * (n as f64) / (pcm_fs as f64)).sin(); 220 | } 221 | } 222 | 223 | pcm.mult_constant_gain(0.1); 224 | 225 | wave_write_16bit_mono_safer3("ex3_1.wav", &pcm); 226 | } 227 | 228 | fn ex3_2() { 229 | let f0 = 500.0; /* 基本周波数 */ 230 | 231 | let pcm_fs = 44100; 232 | let pcm_length = pcm_fs * 1; 233 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 234 | 235 | /* 矩形波 */ 236 | for j in 0..22 { 237 | let i = (2 * j + 1) as f64; 238 | for (n, item) in pcm.s.iter_mut().enumerate() { 239 | *item += 1.0 / i * (2.0 * PI * i * f0 * (n as f64) / (pcm_fs as f64)).sin(); 240 | } 241 | } 242 | 243 | pcm.mult_constant_gain(0.1); 244 | 245 | wave_write_16bit_mono_safer3("ex3_2.wav", &pcm); 246 | } 247 | 248 | fn ex3_3() { 249 | let f0 = 500.0; /* 基本周波数 */ 250 | 251 | let pcm_fs = 44100; 252 | let pcm_length = pcm_fs * 1; 253 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 254 | 255 | /* 三角波 */ 256 | for j in 0..22 { 257 | let i = (2 * j + 1) as f64; 258 | for (n, item) in pcm.s.iter_mut().enumerate() { 259 | *item += 1.0 / i / i 260 | * (PI * i / 2.0).sin() 261 | * (2.0 * PI * i * f0 * (n as f64) / (pcm_fs as f64)).sin(); 262 | } 263 | } 264 | 265 | pcm.mult_constant_gain(0.1); 266 | 267 | wave_write_16bit_mono_safer3("ex3_3.wav", &pcm); 268 | } 269 | 270 | fn ex3_4() { 271 | let f0 = 500.0; /* 基本周波数 */ 272 | 273 | let pcm_fs = 44100; 274 | let pcm_length = pcm_fs * 1; 275 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 276 | 277 | /* コサイン波の重ね合わせによるノコギリ波 */ 278 | for i in 1..=44 { 279 | let i = i as f64; 280 | for (n, item) in pcm.s.iter_mut().enumerate() { 281 | *item += 1.0 / i * (2.0 * PI * i * f0 * (n as f64) / (pcm_fs as f64)).cos(); 282 | } 283 | } 284 | 285 | pcm.mult_constant_gain(0.1); 286 | 287 | wave_write_16bit_mono_safer3("ex3_4.wav", &pcm); 288 | } 289 | 290 | // slow and random; omitted from the test 291 | fn ex3_5() { 292 | let f0 = 1.0; /* 基本周波数 */ 293 | 294 | let pcm_fs = 44100; 295 | let pcm_length = pcm_fs * 1; 296 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 297 | 298 | let mut rng = rand::thread_rng(); 299 | /* 白色雑音 */ 300 | for i in 1..=22050 { 301 | let theta: f64 = rng.gen_range(0.0, 2.0 * PI); 302 | if i % 441 == 0 { 303 | println!("{} / 22050", i); 304 | } 305 | let i = i as f64; 306 | for (n, item) in pcm.s.iter_mut().enumerate() { 307 | *item += (2.0 * PI * i * f0 * (n as f64) / (pcm_fs as f64) + theta).sin(); 308 | } 309 | } 310 | 311 | pcm.mult_constant_gain(0.001); 312 | 313 | wave_write_16bit_mono_safer3("ex3_5.wav", &pcm); 314 | } 315 | 316 | #[allow(non_snake_case)] 317 | fn ex4_1() { 318 | let N = 64; 319 | let X = dft(N, &(Box::new(|_| 1.0) as Box<_>)); 320 | verify_(&X); 321 | } 322 | 323 | #[allow(non_snake_case)] 324 | fn ex4_2() { 325 | let N = 64; 326 | let w = create_Hanning_window(N); /* ハニング窓 */ 327 | 328 | let X = dft(N, &(Box::new(move |n| w[n]) as Box<_>)); 329 | 330 | for (k, item) in X.iter().enumerate() { 331 | assert_close(item.re, 0.0); 332 | assert_close( 333 | item.im, 334 | match k { 335 | 3 | 5 => 4.0, 336 | 4 => -8.0, 337 | 59 | 61 => -4.0, 338 | 60 => 8.0, 339 | _ => 0.0, 340 | }, 341 | ); 342 | } 343 | } 344 | 345 | #[allow(non_snake_case)] 346 | fn ex4_3() { 347 | let N = 64; 348 | let pcm_s = wave_read_16bit_mono_safer3("sine_500hz.wav").s; 349 | 350 | let mut x: Vec> = (0..N) 351 | .map(|n| { 352 | /* 波形 */ 353 | Complex::new(pcm_s[n], 0.0) /* x(n)の実数部と虚数部 */ 354 | }) 355 | .collect(); 356 | 357 | safe_FFT_(&mut x); /* FFTの計算結果はxに上書きされる */ 358 | } 359 | 360 | #[allow(non_snake_case)] 361 | fn ex4_4() { 362 | { 363 | let pcm0_fs = 44100; 364 | let pcm0_length = pcm0_fs * 1; /* 音データの長さ */ 365 | let mut pcm0 = MonoPcm::new16(pcm0_fs, pcm0_length); /* 音データ */ 366 | 367 | let f0 = 500.0; /* 基本周波数 */ 368 | 369 | /* 基本音を含む音 */ 370 | for i in 1..=44 { 371 | for (n, item) in pcm0.s.iter_mut().enumerate() { 372 | *item += (2.0 * PI * i as f64 * f0 * n as f64 / pcm0_fs as f64).sin(); 373 | } 374 | } 375 | 376 | pcm0.mult_constant_gain(0.01); 377 | wave_write_16bit_mono_safer3("ex4_4a.wav", &pcm0); 378 | } 379 | { 380 | let pcm1_fs = 44100; 381 | let pcm1_length = pcm1_fs * 1; /* 音データの長さ */ 382 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); /* 音データ */ 383 | let f0 = 500.0; /* 基本周波数 */ 384 | /* 基本音を含まない音 */ 385 | for i in 2..=44 { 386 | for (n, item) in pcm1.s.iter_mut().enumerate() { 387 | *item += (2.0 * PI * i as f64 * f0 * n as f64 / pcm1_fs as f64).sin(); 388 | } 389 | } 390 | pcm1.mult_constant_gain(0.01); 391 | wave_write_16bit_mono_safer3("ex4_4b.wav", &pcm1); 392 | } 393 | } 394 | 395 | #[allow(non_snake_case)] 396 | fn ex5_1() { 397 | let pcm_fs = 44100; /* 標本化周波数 */ 398 | let pcm_length = pcm_fs * 4; /* 音データの長さ */ 399 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); /* 音データ */ 400 | 401 | /* 振幅の時間エンベロープ */ 402 | let initial_v = 0.5; /* a0[0] = 0.5; */ 403 | let final_v = 0.0; /* a0[pcm_length - 1] = 0.0; */ 404 | let a0 = linear(initial_v, final_v, pcm_length); 405 | 406 | let f0 = 500.0; /* 周波数 */ 407 | for n in 0..pcm_length { 408 | pcm.s[n] = a0[n] * (2.0 * PI * f0 * n as f64 / pcm_fs as f64).sin(); 409 | } 410 | 411 | wave_write_16bit_mono_safer3("ex5_1.wav", &pcm); 412 | } 413 | 414 | #[allow(non_snake_case)] 415 | fn ex5_2() { 416 | let pcm_fs = 44100; /* 標本化周波数 */ 417 | let pcm_length = pcm_fs * 4; /* 音データの長さ */ 418 | 419 | let a0 = 0.5; /* 振幅 */ 420 | /* 周波数の時間エンベロープ */ 421 | let f0 = linear(2500.0, 1500.0, pcm_length); 422 | let g0: Vec = (0..pcm_length) 423 | .map(|n| { 424 | f0[0].mul_add( 425 | n as f64, 426 | (f0[pcm_length - 1] - f0[0]) * n as f64 * n as f64 / (pcm_length - 1) as f64 / 2.0, 427 | ) 428 | }) 429 | .collect(); 430 | 431 | wave_write_16bit_mono_safer3( 432 | "ex5_2.wav", 433 | &MonoPcm::new16_fn( 434 | pcm_fs, 435 | pcm_length, 436 | Box::new(move |n| a0 * (2.0 * PI * g0[n] / pcm_fs as f64).sin()), 437 | ), 438 | ); 439 | } 440 | 441 | fn ex5_3() { 442 | let pcm_fs = 44100; /* 標本化周波数 */ 443 | let pcm_length = (pcm_fs as f64 * 0.2) as usize; /* 音データの長さ */ 444 | let a0 = 0.5; /* 振幅 */ 445 | 446 | /* 周波数の時間エンベロープ */ 447 | let f0 = linear(2500.0, 1500.0, pcm_length); 448 | let mut g0 = vec![0.0; pcm_length]; 449 | 450 | for n in 0..pcm_length { 451 | g0[n] = f0[0].mul_add( 452 | n as f64, 453 | (f0[pcm_length - 1] - f0[0]) * n as f64 * n as f64 / (pcm_length - 1) as f64 / 2.0, 454 | ); 455 | } 456 | 457 | wave_write_16bit_mono_safer3( 458 | "ex5_3.wav", 459 | &MonoPcm::new16_fn( 460 | pcm_fs, 461 | pcm_length, 462 | Box::new(move |n| a0 * (2.0 * PI * g0[n] / pcm_fs as f64).sin()), 463 | ), 464 | ); 465 | } 466 | 467 | fn ex5_4() { 468 | let pcm_fs = 44100; /* 標本化周波数 */ 469 | let pcm_length = pcm_fs * 4; /* 音データの長さ */ 470 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 471 | 472 | let a0 = vec![0.5; pcm_length]; 473 | let a1 = vec![1.0; pcm_length]; 474 | let a2 = vec![0.7; pcm_length]; 475 | let a3 = vec![0.5; pcm_length]; 476 | let a4 = vec![0.3; pcm_length]; 477 | let f0 = vec![440.0; pcm_length]; 478 | let f1 = vec![880.0; pcm_length]; 479 | let f2 = vec![1320.0; pcm_length]; 480 | let f3 = vec![1760.0; pcm_length]; 481 | let f4 = vec![2200.0; pcm_length]; 482 | 483 | /* 加算合成 */ 484 | for n in 0..pcm_length { 485 | pcm.s[n] += a0[n] * (2.0 * PI * f0[n] * n as f64 / pcm_fs as f64).sin(); 486 | pcm.s[n] += a1[n] * (2.0 * PI * f1[n] * n as f64 / pcm_fs as f64).sin(); 487 | pcm.s[n] += a2[n] * (2.0 * PI * f2[n] * n as f64 / pcm_fs as f64).sin(); 488 | pcm.s[n] += a3[n] * (2.0 * PI * f3[n] * n as f64 / pcm_fs as f64).sin(); 489 | pcm.s[n] += a4[n] * (2.0 * PI * f4[n] * n as f64 / pcm_fs as f64).sin(); 490 | } 491 | 492 | pcm.mult_constant_gain(0.1); 493 | 494 | /* フェード処理 */ 495 | for n in 0..(pcm_fs as f64 * 0.01).ceil() as usize { 496 | pcm.s[n] *= n as f64 / (pcm_fs as f64 * 0.01); 497 | pcm.s[pcm_length - n - 1] *= n as f64 / (pcm_fs as f64 * 0.01); 498 | } 499 | 500 | wave_write_16bit_mono_safer3("ex5_4.wav", &pcm); 501 | } 502 | 503 | fn ex5_5() { 504 | let pcm_fs = 44100; /* 標本化周波数 */ 505 | let pcm_length = pcm_fs * 4; /* 音データの長さ */ 506 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); /* 音データ */ 507 | 508 | /* 時間エンベロープ */ 509 | let a0 = exponential_decay(pcm_fs, 1.0, 5.0, 4.0, pcm_length); 510 | let a1 = exponential_decay(pcm_fs, 0.8, 5.0, 2.0, pcm_length); 511 | let a2 = exponential_decay(pcm_fs, 0.6, 5.0, 1.0, pcm_length); 512 | let a3 = exponential_decay(pcm_fs, 0.5, 5.0, 0.5, pcm_length); 513 | let a4 = exponential_decay(pcm_fs, 0.4, 5.0, 0.2, pcm_length); 514 | 515 | let f0 = vec![440.0; pcm_length]; 516 | let f1 = vec![880.0; pcm_length]; 517 | let f2 = vec![1320.0; pcm_length]; 518 | let f3 = vec![1760.0; pcm_length]; 519 | let f4 = vec![2200.0; pcm_length]; 520 | 521 | /* 加算合成 */ 522 | for (n, item) in pcm.s.iter_mut().enumerate() { 523 | *item += a0[n] * (2.0 * PI * f0[n] * n as f64 / pcm_fs as f64).sin(); 524 | *item += a1[n] * (2.0 * PI * f1[n] * n as f64 / pcm_fs as f64).sin(); 525 | *item += a2[n] * (2.0 * PI * f2[n] * n as f64 / pcm_fs as f64).sin(); 526 | *item += a3[n] * (2.0 * PI * f3[n] * n as f64 / pcm_fs as f64).sin(); 527 | *item += a4[n] * (2.0 * PI * f4[n] * n as f64 / pcm_fs as f64).sin(); 528 | } 529 | 530 | pcm.mult_constant_gain(0.1); 531 | 532 | /* フェード処理 */ 533 | for n in 0..(pcm_fs as f64 * 0.01).ceil() as usize { 534 | pcm.s[n] *= n as f64 / (pcm_fs as f64 * 0.01); 535 | pcm.s[pcm_length - n - 1] *= n as f64 / (pcm_fs as f64 * 0.01); 536 | } 537 | 538 | wave_write_16bit_mono_safer3("ex5_5.wav", &pcm); 539 | } 540 | 541 | #[allow(non_snake_case)] 542 | fn ex6_1() { 543 | let pcm0 = wave_read_16bit_mono_safer3("sine_500hz_3500hz.wav"); 544 | 545 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 546 | 547 | let fe = 1000.0 / pcm0.fs as f64; /* エッジ周波数 */ 548 | let delta = 1000.0 / pcm0.fs as f64; /* 遷移帯域幅 */ 549 | let J = determine_J(delta); /* 遅延器の数 */ 550 | 551 | vec![0.0; J + 1]; 552 | let w = create_Hanning_window(J + 1); /* ハニング窓 */ 553 | 554 | let b = get_FIR_LPF(fe, J, &w); /* FIRフィルタの設計 */ 555 | safe_FIR_filtering(&pcm0.s, &mut pcm1.s, pcm1.length, &b, J); 556 | wave_write_16bit_mono_safer3("ex6_1.wav", &pcm1); 557 | } 558 | 559 | #[allow(non_snake_case)] 560 | fn ex6_2() { 561 | let pcm0 = wave_read_16bit_mono_safer3("sine_500hz_3500hz.wav"); 562 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 563 | 564 | let fc = 1000.0 / pcm0.fs as f64; /* 遮断周波数 */ 565 | let Q = 1.0 / 2.0_f64.sqrt(); /* クオリティファクタ */ 566 | let I = 2; /* 遅延器の数 */ 567 | let J = 2; /* 遅延器の数 */ 568 | 569 | let mut a = [0.0; 3]; 570 | let mut b = [0.0; 3]; 571 | 572 | safe_IIR_LPF(fc, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 573 | safe_IIR_filtering(&pcm0.s, &mut pcm1.s, pcm1.length, &a, &b, I, J); 574 | 575 | wave_write_16bit_mono_safer3("ex6_2.wav", &pcm1); 576 | } 577 | 578 | #[allow(non_snake_case)] 579 | fn ex6_3() { 580 | let pcm0 = wave_read_16bit_mono_safer3("sine_500hz_3500hz.wav"); 581 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 582 | 583 | let fe = 1000.0 / pcm0.fs as f64; /* エッジ周波数 */ 584 | let delta = 1000.0 / pcm0.fs as f64; /* 遷移帯域幅 */ 585 | 586 | let J = determine_J(delta); /* 遅延器の数 */ 587 | 588 | let w = create_Hanning_window(J + 1); /* ハニング窓 */ 589 | let b = get_FIR_LPF(fe, J, &w); /* FIRフィルタの設計 */ 590 | 591 | let L: usize = 128; /* フレームの長さ */ 592 | let N = 256; /* DFTのサイズ */ 593 | 594 | let number_of_frame = pcm0.length as usize / L; /* フレームの数 */ 595 | for frame in 0..number_of_frame { 596 | let offset = (L * frame) as usize; 597 | /* X(k) */ 598 | let mut x = vec![Complex::new(0.0, 0.0); N]; 599 | 600 | for n in 0..L { 601 | x[n].re = pcm0.s[offset + n]; 602 | } 603 | safe_FFT_(&mut x); 604 | 605 | /* B(k) */ 606 | let mut b_ = vec![Complex::new(0.0, 0.0); N]; 607 | for m in 0..=J { 608 | b_[m].re = b[m]; 609 | } 610 | safe_FFT_(&mut b_); 611 | 612 | /* フィルタリング */ 613 | let mut y: Vec<_> = (0..N).map(|k| x[k] * b_[k]).collect(); 614 | safe_IFFT_(&mut y); 615 | 616 | /* オーバーラップアド */ 617 | for n in 0..(L * 2) { 618 | if offset + n < pcm1.length as usize { 619 | pcm1.s[offset + n] += y[n].re; 620 | } 621 | } 622 | } 623 | wave_write_16bit_mono_safer3("ex6_3.wav", &pcm1); 624 | } 625 | 626 | #[allow(non_snake_case)] 627 | fn ex6_4() { 628 | let pcm0 = wave_read_16bit_mono_safer3("sine_500hz_3500hz.wav"); 629 | 630 | let N = 256; /* DFTのサイズ */ 631 | 632 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 633 | 634 | let mut b_ = vec![Complex::new(0.0, 0.0); N]; 635 | 636 | let w: Vec = create_Hanning_window(N); /* ハニング窓 */ 637 | 638 | let number_of_frame = (pcm0.length as usize - N / 2) / (N / 2); /* フレームの数 */ 639 | 640 | for frame in 0..number_of_frame { 641 | let offset = N / 2 * frame; 642 | 643 | /* X(n) */ 644 | let mut x: Vec<_> = (0..N) 645 | .map(|n| Complex::new(pcm0.s[offset + n] * w[n], 0.0)) 646 | .collect(); 647 | safe_FFT_(&mut x); 648 | 649 | /* B(k) */ 650 | let fe = 1000.0 / pcm0.fs as f64; /* エッジ周波数 */ 651 | let fe = (fe * N as f64) as usize; 652 | for k in 0..=fe { 653 | b_[k] = Complex::new(1.0, 0.0); 654 | } 655 | for k in (fe + 1)..=N / 2 { 656 | b_[k] = Complex::new(0.0, 0.0); 657 | } 658 | for k in 1..N / 2 { 659 | b_[N - k] = b_[k].conj(); 660 | } 661 | 662 | /* フィルタリング */ 663 | let mut y: Vec<_> = (0..N).map(|k| x[k] * b_[k]).collect(); 664 | safe_IFFT_(&mut y); 665 | 666 | /* オーバーラップアド */ 667 | for (n, item) in y.iter().enumerate() { 668 | pcm1.s[offset + n] += item.re; 669 | } 670 | } 671 | wave_write_16bit_mono_safer3("ex6_4.wav", &pcm1); 672 | } 673 | 674 | // slooooow; omitted from the test 675 | #[allow(non_snake_case)] 676 | fn ex6_5() { 677 | let pcm0 = wave_read_16bit_mono_safer3("drum.wav"); 678 | let pcm1 = wave_read_16bit_mono_safer3("response.wav"); 679 | 680 | let J = pcm1.fs; /* 遅延器の数 */ 681 | 682 | /* フィルタリング */ 683 | let pcm2 = MonoPcm::new16_fn( 684 | pcm0.fs, 685 | pcm0.length, 686 | Box::new(move |n| { 687 | let mut a = 0.0; 688 | for m in 0..=J as usize { 689 | if n >= m { 690 | a += pcm1.s[m] * pcm0.s[n - m]; 691 | } 692 | } 693 | if n % 1000 == 0 { 694 | println!("{} / {}", n, pcm0.length); 695 | } 696 | a 697 | }), 698 | ); 699 | 700 | wave_write_16bit_mono_safer3("ex6_5.wav", &pcm2); 701 | } 702 | -------------------------------------------------------------------------------- /sound_programming/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::pedantic, clippy::nursery)] 2 | #![allow( 3 | clippy::cast_precision_loss, 4 | clippy::cast_sign_loss, 5 | clippy::cast_possible_truncation, 6 | clippy::identity_op, 7 | clippy::cast_possible_wrap, 8 | clippy::cast_lossless, 9 | clippy::erasing_op, 10 | clippy::needless_range_loop 11 | )] 12 | 13 | extern crate num_complex; 14 | extern crate rand; 15 | extern crate wave_utils; 16 | use std::f64::consts::PI; 17 | use wave_utils::MonoPcm; 18 | 19 | pub mod first; 20 | pub mod second; 21 | pub mod third; 22 | 23 | fn sine_wave(pcm: &mut MonoPcm, f0: f64, a: f64, offset: usize, duration: usize) { 24 | /* サイン波 */ 25 | let mut s: Vec = (0..duration) 26 | .map(|n| (2.0 * PI * f0 * (n as f64) / (pcm.fs as f64)).sin() * a) 27 | .collect(); 28 | 29 | /* フェード処理 */ 30 | for n in 0..(pcm.fs as f64 * 0.01).ceil() as usize { 31 | s[n] *= n as f64 / (pcm.fs as f64 * 0.01); 32 | s[duration - n - 1] *= n as f64 / (pcm.fs as f64 * 0.01); 33 | } 34 | 35 | for n in 0..duration as usize { 36 | pcm.s[offset + n] += s[n]; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sound_programming/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate num_complex; 2 | extern crate rand; 3 | extern crate sound_programming; 4 | extern crate wave_utils; 5 | use sound_programming::first::first; 6 | use sound_programming::second::second; 7 | use sound_programming::third::third; 8 | use wave_utils::wave::wave_read_16bit_mono_safer3; 9 | use wave_utils::wave::wave_read_16bit_stereo_safer3; 10 | use wave_utils::wave::wave_read_8bit_mono_safer3; 11 | use wave_utils::wave::wave_read_8bit_stereo_safer3; 12 | use wave_utils::wave::wave_read_IMA_ADPCM_mono_safer3; 13 | use wave_utils::wave::wave_read_PCMA_mono_safer3; 14 | use wave_utils::wave::wave_read_PCMU_mono_safer3; 15 | use wave_utils::wave::wave_write_16bit_mono_safer3; 16 | use wave_utils::wave::wave_write_16bit_stereo_safer3; 17 | use wave_utils::wave::wave_write_8bit_mono_safer3; 18 | use wave_utils::wave::wave_write_8bit_stereo_safer3; 19 | use wave_utils::wave::wave_write_IMA_ADPCM_mono_safer3; 20 | use wave_utils::wave::wave_write_PCMA_mono_safer3; 21 | use wave_utils::wave::wave_write_PCMU_mono_safer3; 22 | 23 | fn main() { 24 | if false { 25 | first(); 26 | } 27 | if true { 28 | second(); 29 | } 30 | if false { 31 | third(); 32 | } 33 | if false { 34 | ex11_7(); 35 | ex11_8(); 36 | ex11_9(); 37 | eightbit(); 38 | } 39 | } 40 | 41 | fn eightbit() { 42 | { 43 | let pcm0 = wave_read_16bit_mono_safer3("ex1_1_a.wav"); /* 音データの入力 */ 44 | let mut pcm1 = pcm0; /* 音データのムーブ */ 45 | pcm1.bits = 8; 46 | 47 | wave_write_8bit_mono_safer3("ex1_1_8bit.wav", &pcm1); /* 音データの出力 */ 48 | } 49 | { 50 | let pcm1 = wave_read_8bit_mono_safer3("ex1_1_8bit.wav"); 51 | let mut pcm2 = pcm1; 52 | pcm2.bits = 16; 53 | wave_write_16bit_mono_safer3("ex1_1_c.wav", &pcm2); /* 音データの出力 */ 54 | } 55 | { 56 | let pcm0 = wave_read_16bit_stereo_safer3("ex1_2_a.wav"); 57 | let mut pcm1 = pcm0; /* 音データのムーブ */ 58 | pcm1.bits = 8; 59 | 60 | wave_write_8bit_stereo_safer3("ex1_2_8bit.wav", &pcm1); 61 | } 62 | { 63 | let pcm1 = wave_read_8bit_stereo_safer3("ex1_2_8bit.wav"); 64 | let mut pcm2 = pcm1; 65 | pcm2.bits = 16; 66 | wave_write_16bit_stereo_safer3("ex1_2_c.wav", &pcm2); /* 音データの出力 */ 67 | } 68 | } 69 | 70 | #[allow(non_snake_case)] 71 | fn ex11_7() { 72 | let pcm0 = wave_read_16bit_mono_safer3("vocal.wav"); 73 | wave_write_PCMU_mono_safer3("pcmu.wav", &pcm0); 74 | let pcm1 = wave_read_PCMU_mono_safer3("pcmu.wav"); 75 | wave_write_16bit_mono_safer3("ex11_7_pcm.wav", &pcm1); 76 | } 77 | 78 | #[allow(non_snake_case)] 79 | fn ex11_8() { 80 | let pcm0 = wave_read_16bit_mono_safer3("vocal.wav"); 81 | wave_write_PCMA_mono_safer3("pcma.wav", &pcm0); 82 | let pcm1 = wave_read_PCMA_mono_safer3("pcma.wav"); 83 | wave_write_16bit_mono_safer3("ex11_8_pcm.wav", &pcm1); 84 | } 85 | 86 | #[allow(non_snake_case)] 87 | fn ex11_9() { 88 | let pcm0 = wave_read_16bit_mono_safer3("vocal.wav"); 89 | wave_write_IMA_ADPCM_mono_safer3("ima_adpcm.wav", &pcm0); 90 | let pcm1 = wave_read_IMA_ADPCM_mono_safer3("ima_adpcm.wav"); 91 | wave_write_16bit_mono_safer3("ex11_9_pcm.wav", &pcm1); 92 | } 93 | -------------------------------------------------------------------------------- /sound_programming/src/second.rs: -------------------------------------------------------------------------------- 1 | extern crate num_complex; 2 | extern crate rand; 3 | 4 | use num_complex::Complex; 5 | use rand::Rng; 6 | use wave_utils::create_Hanning_window; 7 | use wave_utils::determine_J; 8 | use wave_utils::fft::safe_FFT_; 9 | use wave_utils::fft::safe_IFFT_; 10 | use wave_utils::filter::get_FIR_LPF; 11 | use wave_utils::filter::safe_IIR_LPF; 12 | use wave_utils::filter::safe_IIR_filtering; 13 | use wave_utils::filter::safe_IIR_resonator; 14 | use wave_utils::linear; 15 | use wave_utils::mult; 16 | use wave_utils::wave::wave_read_16bit_mono_safer3; 17 | use wave_utils::wave::wave_write_16bit_mono_safer3; 18 | use wave_utils::MonoPcm; 19 | 20 | pub fn second() { 21 | ex7_1(); 22 | ex7_2(); 23 | ex7_3(); 24 | ex7_4(); 25 | ex8_1(); 26 | ex8_2(); 27 | ex8_3(); 28 | if false { 29 | ex8_4(); // random 30 | ex8_5(); // random 31 | ex8_6(); // random 32 | } 33 | ex8_7(); 34 | ex8_8(); 35 | ex8_9(); 36 | ex8_10(); 37 | ex8_11(); 38 | ex8_12(); 39 | } 40 | 41 | #[allow(non_snake_case)] 42 | fn ex7_1() { 43 | let pcm0 = wave_read_16bit_mono_safer3("ex7_1_pulse_train.wav"); 44 | 45 | let mut fc = vec![0.0; pcm0.length as usize]; 46 | /* LPFの遮断周波数 */ 47 | for n in 0..pcm0.length as usize { 48 | fc[n] = 10000.0 * (-5.0 * n as f64 / pcm0.length as f64).exp(); 49 | } 50 | let Q = 1.0 / 2.0_f64.sqrt(); /* クオリティファクタ */ 51 | let I = 2; /* 遅延器の数 */ 52 | let J = 2; /* 遅延器の数 */ 53 | 54 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 55 | 56 | let mut a = [0.0; 3]; 57 | let mut b = [0.0; 3]; 58 | 59 | filter_with_IIR_LPF(&pcm0, &mut pcm1, Q, I, J, &fc, &mut a, &mut b); 60 | 61 | wave_write_16bit_mono_safer3("ex7_1.wav", &pcm1); 62 | } 63 | 64 | #[allow(non_snake_case, clippy::too_many_arguments)] 65 | fn filter_with_IIR_LPF( 66 | pcm0: &MonoPcm, 67 | pcm1: &mut MonoPcm, 68 | Q: f64, 69 | I: usize, 70 | J: usize, 71 | fc: &[f64], 72 | mut a: &mut [f64], 73 | mut b: &mut [f64], 74 | ) { 75 | for n in 0..pcm1.length as usize { 76 | safe_IIR_LPF(fc[n] / pcm1.fs as f64, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 77 | 78 | for m in 0..=J { 79 | if n >= m { 80 | pcm1.s[n] += b[m] * pcm0.s[n - m]; 81 | } 82 | } 83 | for m in 1..=I { 84 | if n >= m { 85 | pcm1.s[n] += -a[m] * pcm1.s[n - m]; 86 | } 87 | } 88 | } 89 | } 90 | 91 | #[allow(non_snake_case)] 92 | fn ex7_2() { 93 | let mut a = [0.0; 3]; 94 | let mut b = [0.0; 3]; 95 | let pcm0 = wave_read_16bit_mono_safer3("white_noise.wav"); 96 | let mut fc = vec![0.0; pcm0.length as usize]; 97 | /* LPFの遮断周波数 */ 98 | for n in 0..pcm0.length as usize { 99 | fc[n] = 10000.0 * (-5.0 * n as f64 / pcm0.length as f64).exp(); 100 | } 101 | let Q = 1.0 / 2.0_f64.sqrt(); /* クオリティファクタ */ 102 | let I = 2; /* 遅延器の数 */ 103 | let J = 2; /* 遅延器の数 */ 104 | 105 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); /* 音データ */ 106 | 107 | filter_with_IIR_LPF(&pcm0, &mut pcm1, Q, I, J, &fc, &mut a, &mut b); 108 | 109 | wave_write_16bit_mono_safer3("ex7_2.wav", &pcm1); 110 | } 111 | 112 | #[allow(non_snake_case)] 113 | fn ex7_3() { 114 | let mut a = [0.0; 3]; 115 | let mut b = [0.0; 3]; 116 | let pcm0 = wave_read_16bit_mono_safer3("ex7_3_pulse_train.wav"); 117 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 118 | 119 | let mut s = vec![0.0; pcm1.length as usize]; 120 | let F = [ 121 | 800.0, /* F1の周波数 */ 122 | 1200.0, /* F2の周波数 */ 123 | 2500.0, /* F3の周波数 */ 124 | 3500.0, 125 | ]; /* F4の周波数 */ 126 | 127 | let B = [ 128 | 100.0, /* F1の帯域幅 */ 129 | 100.0, /* F2の帯域幅 */ 130 | 100.0, /* F3の帯域幅 */ 131 | 100.0, 132 | ]; /* F4の帯域幅 */ 133 | 134 | let I = 2; /* 遅延器の数 */ 135 | let J = 2; /* 遅延器の数 */ 136 | 137 | for num in 0..4 { 138 | /* IIRフィルタの設計 */ 139 | safe_IIR_resonator(F[num] / pcm0.fs as f64, F[num] / B[num], &mut a, &mut b); 140 | safe_IIR_filtering(&pcm0.s, &mut s, pcm0.length, &a, &b, I, J); /* フィルタリング */ 141 | for n in 0..pcm1.length as usize { 142 | pcm1.s[n] += s[n]; 143 | s[n] = 0.0; 144 | } 145 | } 146 | 147 | /* ディエンファシス処理 */ 148 | s[0] = pcm1.s[0]; 149 | for n in 1..pcm1.length as usize { 150 | s[n] = s[n - 1].mul_add(0.98, pcm1.s[n]); 151 | } 152 | pcm1.s[..(pcm1.length as usize)].clone_from_slice(&s[..(pcm1.length as usize)]); 153 | wave_write_16bit_mono_safer3("ex7_3.wav", &pcm1); 154 | } 155 | 156 | #[allow(non_snake_case)] 157 | fn ex7_4() { 158 | let pcm0 = wave_read_16bit_mono_safer3("synth.wav"); 159 | let mut pcm1 = wave_read_16bit_mono_safer3("vocal.wav"); 160 | let mut pcm2 = MonoPcm::blank_copy(&pcm0); 161 | 162 | let mut s = vec![0.0; pcm0.length]; /* 音データ */ 163 | /* プリエンファシス処理 */ 164 | s[0] = 0.0; 165 | for n in 1..pcm1.length { 166 | s[n] = pcm1.s[n] - 0.98 * pcm1.s[n - 1]; 167 | } 168 | pcm1.s[..pcm1.length].clone_from_slice(&s[..pcm1.length]); 169 | 170 | let N = 1024; /* DFTのサイズ */ 171 | 172 | let w = create_Hanning_window(N); /* ハニング窓 */ 173 | let number_of_frame = (pcm0.length - N / 2) / (N / 2); /* フレームの数 */ 174 | let band_width = 8; 175 | let number_of_band = N / 2 / band_width; 176 | 177 | for frame in 0..number_of_frame { 178 | let offset = N / 2 * frame; 179 | /* X(n) */ 180 | let mut x: Vec<_> = (0..N) 181 | .map(|n| Complex::new(pcm0.s[offset + n] * w[n], 0.0)) 182 | .collect(); 183 | safe_FFT_(&mut x); 184 | 185 | /* B(k) */ 186 | let mut b_: Vec<_> = (0..N) 187 | .map(|n| Complex::new(pcm1.s[offset + n] * w[n], 0.0)) 188 | .collect(); 189 | safe_FFT_(&mut b_); 190 | 191 | for item in &mut b_ { 192 | *item = Complex::new(item.norm_sqr().sqrt(), 0.0); 193 | } 194 | 195 | for band in 0..number_of_band { 196 | let offset = band_width * band; 197 | let mut a = 0.0; 198 | for k in 0..band_width { 199 | a += b_[offset + k].re; 200 | } 201 | a /= band_width as f64; 202 | for k in 0..band_width { 203 | b_[offset + k].re = a; 204 | } 205 | } 206 | b_[0].re = 0.0; 207 | b_[N / 2].re = 0.0; 208 | for k in 1..N / 2 { 209 | b_[N - k].re = b_[k].re; 210 | } 211 | 212 | /* フィルタリング */ 213 | let mut y: Vec<_> = (0..N).map(|k| x[k] * b_[k]).collect(); 214 | safe_IFFT_(&mut y); 215 | 216 | let offset = N / 2 * frame; 217 | /* オーバーラップアド */ 218 | for (n, item) in y.iter().enumerate() { 219 | pcm2.s[offset + n] += item.re; 220 | } 221 | } 222 | wave_write_16bit_mono_safer3("ex7_4.wav", &pcm2); 223 | } 224 | 225 | #[allow(non_snake_case)] 226 | fn ex8_1() { 227 | let pcm_fs = 44100; /* 標本化周波数 */ 228 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 229 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 230 | 231 | let f0 = 500.0; /* 基本周波数 */ 232 | /* ノコギリ波 */ 233 | let t0 = pcm_fs / f0 as usize; /* 基本周期 */ 234 | let mut m = 0; 235 | for n in 0..pcm_length { 236 | pcm.s[n] = 1.0 - 2.0 * (m as f64) / (t0 as f64); 237 | 238 | m += 1; 239 | if m >= t0 { 240 | m = 0; 241 | } 242 | } 243 | pcm.mult_constant_gain(0.1); 244 | 245 | wave_write_16bit_mono_safer3("ex8_1.wav", &pcm); 246 | } 247 | 248 | #[allow(non_snake_case)] 249 | fn ex8_2() { 250 | let pcm_fs = 44100; /* 標本化周波数 */ 251 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 252 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 253 | 254 | let f0 = 500.0; /* 基本周波数 */ 255 | 256 | /* 矩形波 */ 257 | let t0 = (pcm.fs as f64 / f0) as usize; /* 基本周期 */ 258 | let mut m = 0; 259 | for n in 0..pcm.length { 260 | pcm.s[n] = if (m as f64) < t0 as f64 / 2.0 { 261 | 1.0 262 | } else { 263 | -1.0 264 | }; 265 | 266 | m += 1; 267 | if m >= t0 { 268 | m = 0; 269 | } 270 | } 271 | pcm.mult_constant_gain(0.1); 272 | wave_write_16bit_mono_safer3("ex8_2.wav", &pcm); 273 | } 274 | 275 | fn ex8_3() { 276 | let pcm_fs = 44100; /* 標本化周波数 */ 277 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 278 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 279 | 280 | let f0 = 500.0; /* 基本周波数 */ 281 | /* 三角波 */ 282 | let t0 = (pcm_fs as f64 / f0) as usize; /* 基本周期 */ 283 | let mut m = 0; 284 | for n in 0..pcm_length { 285 | pcm.s[n] = if (m as f64) < t0 as f64 / 2.0 { 286 | -1.0 + 4.0 * m as f64 / t0 as f64 287 | } else { 288 | 3.0 - 4.0 * m as f64 / t0 as f64 289 | }; 290 | 291 | m += 1; 292 | if m >= t0 { 293 | m = 0; 294 | } 295 | } 296 | pcm.mult_constant_gain(0.1); 297 | wave_write_16bit_mono_safer3("ex8_3.wav", &pcm); 298 | } 299 | 300 | // random; omitted from the test 301 | fn ex8_4() { 302 | let pcm_fs = 44100; /* 標本化周波数 */ 303 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 304 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 305 | 306 | let mut rng = rand::thread_rng(); 307 | /* 白色雑音 */ 308 | for n in 0..pcm_length { 309 | pcm.s[n] = rng.gen_range(-1.0, 1.0); 310 | } 311 | pcm.mult_constant_gain(0.1); 312 | wave_write_16bit_mono_safer3("ex8_4.wav", &pcm); 313 | } 314 | 315 | // random; omitted from the test 316 | fn ex8_5() { 317 | let pcm_fs = 44100; /* 標本化周波数 */ 318 | let pcm_length = pcm_fs * 8; /* 音データの長さ */ 319 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 320 | 321 | let mut rng = rand::thread_rng(); 322 | 323 | /* 白色雑音 */ 324 | for n in 0..pcm_length { 325 | pcm.s[n] = rng.gen_range(-1.0, 1.0); 326 | } 327 | 328 | let mut e = vec![0.0; pcm_length]; 329 | let te = pcm_fs * 2; /* 単調増加または単調減少にかかる時間 */ 330 | 331 | /* 時間エンベロープ */ 332 | let mut m = 0; 333 | for n in 0..pcm_length { 334 | e[n] = if m < te { 335 | m as f64 / te as f64 336 | } else { 337 | 1.0 - (m as f64 - te as f64) / te as f64 338 | }; 339 | 340 | m += 1; 341 | if m >= te * 2 { 342 | m = 0; 343 | } 344 | } 345 | pcm.mult_constant_gain(0.1); 346 | wave_write_16bit_mono_safer3("ex8_5.wav", &pcm); 347 | } 348 | 349 | fn square_wave(pcm: &mut MonoPcm, f0: f64, gain: f64, offset: usize, duration: usize) { 350 | let mut s = vec![0.0; duration]; 351 | /* 矩形波 */ 352 | let t0 = (pcm.fs as f64 / f0) as usize; /* 基本周期 */ 353 | let mut m = 0; 354 | for n in 0..duration { 355 | s[n] = if (m as f64) < t0 as f64 / 2.0 { 356 | 1.0 357 | } else { 358 | -1.0 359 | }; 360 | 361 | m += 1; 362 | if m >= t0 { 363 | m = 0; 364 | } 365 | } 366 | 367 | for n in 0..duration { 368 | s[n] *= gain; 369 | } 370 | 371 | for n in 0..duration { 372 | pcm.s[offset + n] += s[n]; 373 | } 374 | } 375 | 376 | fn triangle_wave(pcm: &mut MonoPcm, f0: f64, gain: f64, offset: usize, duration: usize) { 377 | let mut s = vec![0.0; duration]; 378 | /* 三角波 */ 379 | let t0 = (pcm.fs as f64 / f0) as usize; /* 基本周期 */ 380 | let mut m = 0; 381 | for n in 0..duration { 382 | s[n] = if (m as f64) < t0 as f64 / 2.0 { 383 | -1.0 + 4.0 * m as f64 / t0 as f64 384 | } else { 385 | 3.0 - 4.0 * m as f64 / t0 as f64 386 | }; 387 | m += 1; 388 | if m >= t0 { 389 | m = 0; 390 | } 391 | } 392 | for n in 0..duration { 393 | s[n] *= gain; 394 | } 395 | for n in 0..duration { 396 | pcm.s[offset + n] += s[n]; 397 | } 398 | } 399 | 400 | fn white_noise(pcm: &mut MonoPcm, gain: f64, offset: usize, duration: usize) { 401 | let mut s = vec![0.0; duration]; 402 | let mut rng = rand::thread_rng(); 403 | /* 白色雑音 */ 404 | for n in 0..duration { 405 | s[n] = rng.gen_range(-1.0, 1.0); 406 | } 407 | for n in 0..duration { 408 | s[n] *= gain; 409 | } 410 | for n in 0..duration { 411 | pcm.s[offset + n] += s[n]; 412 | } 413 | } 414 | 415 | // random; omitted from the test 416 | fn ex8_6() { 417 | let pcm_fs = 44100; /* 標本化周波数 */ 418 | let pcm_length = 7000 * 16; /* 音データの長さ */ 419 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); /* 音データ */ 420 | 421 | /* メロディパート */ 422 | square_wave(&mut pcm, 659.26, 0.1, 7000 * 0, 6125); /* E5 */ 423 | square_wave(&mut pcm, 659.26, 0.1, 7000 * 1, 6125); /* E5 */ 424 | square_wave(&mut pcm, 659.26, 0.1, 7000 * 3, 6125); /* E5 */ 425 | square_wave(&mut pcm, 523.25, 0.1, 7000 * 5, 6125); /* C5 */ 426 | square_wave(&mut pcm, 659.26, 0.1, 7000 * 6, 6125); /* E5 */ 427 | square_wave(&mut pcm, 783.99, 0.1, 7000 * 8, 6125); /* G5 */ 428 | square_wave(&mut pcm, 392.00, 0.1, 7000 * 12, 6125); /* G4 */ 429 | 430 | /* ベースパート */ 431 | triangle_wave(&mut pcm, 146.83, 0.2, 7000 * 0, 6125); /* D3 */ 432 | triangle_wave(&mut pcm, 146.83, 0.2, 7000 * 1, 6125); /* D3 */ 433 | triangle_wave(&mut pcm, 146.83, 0.2, 7000 * 3, 6125); /* D3 */ 434 | triangle_wave(&mut pcm, 146.83, 0.2, 7000 * 5, 6125); /* D3 */ 435 | triangle_wave(&mut pcm, 146.83, 0.2, 7000 * 6, 6125); /* D3 */ 436 | triangle_wave(&mut pcm, 196.00, 0.2, 7000 * 8, 6125); /* G3 */ 437 | triangle_wave(&mut pcm, 196.00, 0.2, 7000 * 12, 6125); /* G3 */ 438 | 439 | /* パーカッション */ 440 | white_noise(&mut pcm, 0.1, 7000 * 0, 4000); 441 | white_noise(&mut pcm, 0.1, 7000 * 2, 1000); 442 | white_noise(&mut pcm, 0.1, 7000 * 3, 4000); 443 | white_noise(&mut pcm, 0.1, 7000 * 5, 1000); 444 | white_noise(&mut pcm, 0.1, 7000 * 6, 4000); 445 | white_noise(&mut pcm, 0.1, 7000 * 8, 4000); 446 | white_noise(&mut pcm, 0.1, 7000 * 11, 4000); 447 | white_noise(&mut pcm, 0.1, 7000 * 13, 1000); 448 | white_noise(&mut pcm, 0.1, 7000 * 14, 1000); 449 | white_noise(&mut pcm, 0.1, 7000 * 15, 1000); 450 | 451 | wave_write_16bit_mono_safer3("ex8_6.wav", &pcm); 452 | } 453 | 454 | fn ex8_7() { 455 | let pcm_fs = 44100; /* 標本化周波数 */ 456 | let pcm_length = (pcm_fs as f64 * 0.6) as usize - 1; /* 音データの長さ */ 457 | // -1 is here to match the file with the original data 458 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 459 | 460 | let mut f0 = vec![0.0; pcm_length]; 461 | /* 基本周波数 */ 462 | for n in 0..mult(pcm_fs, 0.1) as usize { 463 | f0[n] = 987.77; /* B5 */ 464 | } 465 | for n in mult(pcm_fs, 0.1) as usize..pcm_length { 466 | f0[n] = 1318.51; /* E6 */ 467 | } 468 | 469 | /* 矩形波 */ 470 | let mut t0 = (pcm_fs as f64 / f0[0]) as usize; /* 矩形波の基本周期 */ 471 | let mut m = 0; 472 | for n in 0..pcm_length { 473 | pcm.s[n] = if (m as f64) < t0 as f64 / 2.0 { 474 | 1.0 475 | } else { 476 | -1.0 477 | }; 478 | 479 | m += 1; 480 | if m >= t0 { 481 | t0 = (pcm_fs as f64 / f0[n]) as usize; /* 矩形波の基本周期 */ 482 | m = 0; 483 | } 484 | } 485 | let mut e = vec![0.0; pcm_length]; 486 | let pe = pcm_length; /* 単調減少にかかる時間 */ 487 | 488 | /* 時間エンベロープ */ 489 | for n in 0..pcm_length { 490 | e[n] = 1.0 - n as f64 / pe as f64; 491 | } 492 | let gain = 0.1; /* ゲイン */ 493 | 494 | for n in 0..pcm_length { 495 | pcm.s[n] *= e[n] * gain; 496 | } 497 | 498 | wave_write_16bit_mono_safer3("ex8_7.wav", &pcm); 499 | } 500 | 501 | fn ex8_8() { 502 | let pcm_fs = 44100; /* 標本化周波数 */ 503 | let pcm_length = (pcm_fs as f64 * 0.6) as usize - 1; /* 音データの長さ */ 504 | // -1 is here to match the file with the original data 505 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 506 | 507 | /* 基本周波数 */ 508 | let mut f0 = vec![0.0; pcm_length]; 509 | for n in 0..(pcm_fs as f64 * 0.2) as usize { 510 | f0[n] = 440.0; 511 | } 512 | for n in (pcm_fs as f64 * 0.2) as usize..pcm_length { 513 | f0[n] = 440.0 514 | + (880.0 - 440.0) * (n as f64 - pcm_fs as f64 * 0.2) 515 | / (pcm_length as f64 - 1.0 - pcm_fs as f64 * 0.2); 516 | } 517 | /* 矩形波 */ 518 | let mut t0 = (pcm_fs as f64 / f0[0]) as usize; /* 矩形波の基本周期 */ 519 | let mut m = 0; 520 | for n in 0..pcm_length { 521 | pcm.s[n] = if (m as f64) < t0 as f64 / 2.0 { 522 | 1.0 523 | } else { 524 | -1.0 525 | }; 526 | m += 1; 527 | if m >= t0 { 528 | t0 = (pcm_fs as f64 / f0[n]) as usize; /* 矩形波の基本周期 */ 529 | m = 0; 530 | } 531 | } 532 | 533 | let mut e = vec![0.0; pcm_length]; 534 | let pe = pcm_length; /* 単調減少にかかる時間 */ 535 | /* 時間エンベロープ */ 536 | for n in 0..pcm_length { 537 | e[n] = 1.0 - n as f64 / pe as f64; 538 | } 539 | 540 | let gain = 0.1; /* ゲイン */ 541 | for n in 0..pcm_length { 542 | pcm.s[n] *= e[n] * gain; 543 | } 544 | wave_write_16bit_mono_safer3("ex8_8.wav", &pcm); 545 | } 546 | 547 | fn ex8_9() { 548 | let pcm_fs = 8000; /* 標本化周波数 */ 549 | let pcm_length = pcm_fs * 2; /* 音データの長さ */ 550 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 551 | 552 | let f0 = linear(500.0, 3500.0, pcm_length); 553 | 554 | /* ノコギリ波 */ 555 | let mut t0 = (pcm_fs as f64 / f0[0]) as usize; /* 基本周期 */ 556 | let mut m = 0; 557 | for n in 0..pcm_length { 558 | pcm.s[n] = 1.0 - 2.0 * m as f64 / t0 as f64; 559 | 560 | m += 1; 561 | if m >= t0 { 562 | t0 = (pcm_fs as f64 / f0[n]) as usize; /* 基本周期 */ 563 | m = 0; 564 | } 565 | } 566 | pcm.mult_constant_gain(0.1); 567 | 568 | wave_write_16bit_mono_safer3("ex8_9.wav", &pcm); 569 | } 570 | 571 | #[allow(non_snake_case)] 572 | fn ex8_10() { 573 | let pcm0_fs = 192_000; /* 標本化周波数 */ 574 | let _pcm0_bits = 16; /* 量子化精度 */ 575 | let pcm0_length = pcm0_fs * 2; /* 音データの長さ */ 576 | 577 | /* 基本周波数 */ 578 | let f0 = linear(500.0, 3500.0, pcm0_length); 579 | 580 | /* ノコギリ波 */ 581 | let pcm0 = MonoPcm::new16_sawtooth_with_varying_freq(pcm0_fs, pcm0_length, &f0); 582 | 583 | let pcm1_fs = 8000; /* 標本化周波数 */ 584 | let pcm1_length = pcm1_fs * 2; /* 音データの長さ */ 585 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); 586 | let ratio = pcm0_fs / pcm1_fs; /* ダウンサンプリングのレシオ */ 587 | let fe = 0.45 / ratio as f64; /* エッジ周波数 */ 588 | let delta = 0.1 / ratio as f64; /* 遷移帯域幅 */ 589 | let J = determine_J(delta); /* 遅延器の数 */ 590 | let w = create_Hanning_window(J + 1); /* ハニング窓 */ 591 | let b = get_FIR_LPF(fe, J, &w); /* FIRフィルタの設計 */ 592 | 593 | /* フィルタリング */ 594 | for n in 0..pcm1_length { 595 | for m in 0..=J { 596 | if n * ratio + J / 2 >= m && n * ratio + J / 2 < pcm0_length + m { 597 | pcm1.s[n] += b[m] * pcm0.s[n * ratio + J / 2 - m]; 598 | } 599 | } 600 | } 601 | pcm1.mult_constant_gain(0.1); 602 | wave_write_16bit_mono_safer3("ex8_10.wav", &pcm1); 603 | } 604 | 605 | fn ex8_11() { 606 | let pcm0_fs = 192_000; /* 標本化周波数 */ 607 | let pcm0_length = pcm0_fs * 2; /* 音データの長さ */ 608 | 609 | /* 基本周波数 */ 610 | let f0 = linear(500.0, 3500.0, pcm0_length); 611 | 612 | /* ノコギリ波 */ 613 | let pcm0 = MonoPcm::new16_sawtooth_with_varying_freq(pcm0_fs, pcm0_length, &f0); 614 | 615 | let pcm1_fs = 8000; /* 標本化周波数 */ 616 | let pcm1_length = pcm1_fs * 2; /* 音データの長さ */ 617 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); 618 | 619 | let ratio = pcm0_fs / pcm1_fs; /* ダウンサンプリングのレシオ */ 620 | 621 | for n in 0..pcm1_length { 622 | pcm1.s[n] = pcm0.s[n * ratio]; 623 | } 624 | 625 | pcm1.mult_constant_gain(0.1); 626 | 627 | wave_write_16bit_mono_safer3("ex8_11.wav", &pcm1); 628 | } 629 | 630 | #[allow(non_snake_case)] 631 | fn ex8_12() { 632 | let pcm0_length = 192_000 * 2; 633 | 634 | /* 基本周波数 */ 635 | let f0 = linear(500.0, 3500.0, pcm0_length); 636 | 637 | /* ノコギリ波 */ 638 | let pcm0 = MonoPcm::new16_sawtooth_with_varying_freq(192_000, pcm0_length, &f0); 639 | 640 | let mut pcm1 = MonoPcm::new16(8000, 8000 * 2); 641 | let ratio = pcm0.fs / pcm1.fs; /* ダウンサンプリングのレシオ */ 642 | let fe = 0.45 / ratio as f64; /* エッジ周波数 */ 643 | let delta = 0.1 / ratio as f64; /* 遷移帯域幅 */ 644 | let J = determine_J(delta); /* 遅延器の数 */ 645 | let w = create_Hanning_window(J + 1); /* ハニング窓 */ 646 | let b = get_FIR_LPF(fe, J, &w); /* FIRフィルタの設計 */ 647 | for n in 0..pcm1.length { 648 | for m in 0..=J { 649 | if n * ratio + J / 2 >= m && n * ratio + J / 2 < pcm0.length + m { 650 | pcm1.s[n] += b[m] * pcm0.s[n * ratio + J / 2 - m]; 651 | } 652 | } 653 | } 654 | let mut pcm2 = MonoPcm::new16(192_000, 192_000 * 2); 655 | /* 0を挿入する */ 656 | for n in 0..pcm1.length { 657 | pcm2.s[n * ratio] = pcm1.s[n]; 658 | } 659 | 660 | let mut pcm3 = MonoPcm::new16(192_000, 192_000 * 2); 661 | for n in 0..pcm3.length { 662 | for m in 0..=J { 663 | if n + J / 2 >= m && n + J / 2 < pcm2.length + m { 664 | pcm3.s[n] += b[m] * pcm2.s[n + J / 2 - m]; 665 | } 666 | } 667 | } 668 | 669 | pcm3.mult_constant_gain(ratio as f64 * 0.1); 670 | 671 | wave_write_16bit_mono_safer3("ex8_12.wav", &pcm3); 672 | } 673 | -------------------------------------------------------------------------------- /sound_programming/src/third.rs: -------------------------------------------------------------------------------- 1 | extern crate num_complex; 2 | extern crate rand; 3 | extern crate wave_utils; 4 | use std::f64::consts::PI; 5 | use wave_utils::filter::safe_IIR_LPF; 6 | use wave_utils::lfo; 7 | use wave_utils::mult; 8 | use wave_utils::safe_ADSR; 9 | use wave_utils::sinc; 10 | use wave_utils::wave::wave_read_16bit_mono_safer3; 11 | use wave_utils::wave::wave_write_16bit_mono_safer3; 12 | use wave_utils::MonoPcm; 13 | 14 | pub fn third() { 15 | ex9_1(); 16 | ex9_2(); 17 | ex9_3(); 18 | ex9_4(); 19 | ex9_5(); 20 | ex9_6(); 21 | ex9_7(); 22 | ex9_8(); 23 | ex9_9(); 24 | ex9_10(); 25 | ex9_11(); 26 | ex10_1(); 27 | ex10_2(); 28 | ex10_3(); 29 | ex10_4(); 30 | ex10_5(); 31 | ex10_6(); 32 | ex11_1(); 33 | ex11_2(); 34 | ex11_3(); 35 | ex11_4(); 36 | ex11_5(); 37 | ex11_6(); 38 | } 39 | 40 | fn ex9_1() { 41 | let pcm_fs = 44100; /* 標本化周波数 */ 42 | let pcm_length = pcm_fs * 2; /* 音データの長さ */ 43 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 44 | let vco = 500.0; /* 基本周波数 */ 45 | 46 | /* ノコギリ波 */ 47 | let t0 = (pcm.fs as f64 / vco) as usize; /* 基本周期 */ 48 | { 49 | let mut m = 0; 50 | for n in 0..pcm_length { 51 | pcm.s[n] = 1.0 - 2.0 * m as f64 / t0 as f64; 52 | 53 | m += 1; 54 | if m >= t0 { 55 | m = 0; 56 | } 57 | } 58 | } 59 | 60 | let vca = lfo( 61 | &pcm, 1.0, 0.2, /* LFOの振幅 */ 62 | 2.0, /* LFOの周波数 */ 63 | ); 64 | 65 | let gain = 0.1; /* ゲイン */ 66 | 67 | pcm.mult_varying_gain(&vca, gain); 68 | 69 | wave_write_16bit_mono_safer3("ex9_1.wav", &pcm); 70 | } 71 | 72 | fn ex9_2() { 73 | let pcm_fs = 44100; /* 標本化周波数 */ 74 | let pcm_length = pcm_fs * 2; /* 音データの長さ */ 75 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 76 | let vco = lfo( 77 | &pcm, 500.0, /* Hz */ 78 | 100.0, /* LFOの振幅 */ 79 | 2.0, /* LFOの周波数 */ 80 | ); 81 | 82 | /* ノコギリ波 */ 83 | let mut t0 = (pcm.fs as f64 / vco[0]) as usize; /* 基本周期 */ 84 | let mut m = 0; 85 | for n in 0..pcm.length { 86 | pcm.s[n] = 1.0 - 2.0 * m as f64 / t0 as f64; 87 | 88 | m += 1; 89 | if m >= t0 { 90 | t0 = (pcm.fs as f64 / vco[n]) as usize; /* 基本周期 */ 91 | m = 0; 92 | } 93 | } 94 | 95 | pcm.mult_constant_gain(0.1); 96 | wave_write_16bit_mono_safer3("ex9_2.wav", &pcm); 97 | } 98 | 99 | #[allow(non_snake_case)] 100 | fn ex9_3() { 101 | let pcm0_fs = 44100; 102 | let pcm0_length = 44100 * 2; 103 | let mut pcm0 = MonoPcm::new16(pcm0_fs, pcm0_length); 104 | 105 | let vco = 500.0; /* 基本周波数 */ 106 | 107 | /* ノコギリ波 */ 108 | let t0 = (pcm0.fs as f64 / vco) as usize; /* 基本周期 */ 109 | let mut m = 0; 110 | for n in 0..pcm0.length { 111 | pcm0.s[n] = 1.0 - 2.0 * m as f64 / t0 as f64; 112 | 113 | m += 1; 114 | if m >= t0 { 115 | m = 0; 116 | } 117 | } 118 | 119 | let vcf = lfo( 120 | &pcm0, 1000.0, /* Hz */ 121 | 800.0, /* LFOの振幅 */ 122 | 2.0, /* LFOの周波数 */ 123 | ); 124 | 125 | let Q = 5.0; /* レゾナンス */ 126 | let I = 2; /* 遅延器の数 */ 127 | let J = 2; /* 遅延器の数 */ 128 | 129 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 130 | 131 | let mut a = [0.0; 3]; 132 | let mut b = [0.0; 3]; 133 | /* フィルタリング */ 134 | for n in 0..pcm1.length { 135 | safe_IIR_LPF(vcf[n] / pcm1.fs as f64, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 136 | 137 | for m in 0..=J { 138 | if n >= m { 139 | pcm1.s[n] += b[m] * pcm0.s[n - m]; 140 | } 141 | } 142 | for m in 1..=I { 143 | if n >= m { 144 | pcm1.s[n] += -a[m] * pcm1.s[n - m]; 145 | } 146 | } 147 | } 148 | 149 | pcm1.mult_constant_gain(0.1); 150 | wave_write_16bit_mono_safer3("ex9_3.wav", &pcm1); 151 | } 152 | 153 | #[allow(non_snake_case)] 154 | fn ex9_4() { 155 | let pcm0_fs = 44100; /* 標本化周波数 */ 156 | let pcm0_length = pcm0_fs * 4; /* 音データの長さ */ 157 | let mut pcm0 = MonoPcm::new16(pcm0_fs, pcm0_length); 158 | 159 | let vco = 440.0; /* 基本周波数 */ 160 | 161 | /* ノコギリ波 */ 162 | let t0 = (pcm0.fs as f64 / vco) as usize; /* 基本周期 */ 163 | let mut m = 0; 164 | for n in 0..pcm0.length { 165 | pcm0.s[n] = 1.0 - 2.0 * m as f64 / t0 as f64; 166 | 167 | m += 1; 168 | if m >= t0 { 169 | m = 0; 170 | } 171 | } 172 | 173 | let vcf = 1500.0; /* 遮断周波数 */ 174 | let Q = 5.0; /* レゾナンス */ 175 | let I = 2; /* 遅延器の数 */ 176 | let J = 2; /* 遅延器の数 */ 177 | let mut a = [0.0; 3]; 178 | let mut b = [0.0; 3]; 179 | safe_IIR_LPF(vcf / pcm0.fs as f64, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 180 | 181 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 182 | 183 | /* フィルタリング */ 184 | for n in 0..pcm1.length { 185 | for m in 0..=J { 186 | if n >= m { 187 | pcm1.s[n] += b[m] * pcm0.s[n - m]; 188 | } 189 | } 190 | for m in 1..=I { 191 | if n >= m { 192 | pcm1.s[n] += -a[m] * pcm1.s[n - m]; 193 | } 194 | } 195 | } 196 | 197 | let mut vca = vec![0.0; pcm0.length]; /* 振幅 */ 198 | let gate = pcm1.fs * 4; 199 | let duration = pcm1.fs * 4; 200 | let A = 0; 201 | let D = 0; 202 | let S = 1.0; 203 | let R = 0; 204 | safe_ADSR(&mut vca, A, D, S, R, gate, duration); 205 | let gain = 0.1; /* ゲイン */ 206 | pcm1.mult_varying_gain(&vca, gain); 207 | 208 | /* フェード処理 */ 209 | for n in 0..(pcm1.fs as f64 * 0.01).ceil() as usize { 210 | pcm1.s[n] *= n as f64 / (pcm1.fs as f64 * 0.01); 211 | pcm1.s[pcm1.length - n - 1] *= n as f64 / (pcm1.fs as f64 * 0.01); 212 | } 213 | wave_write_16bit_mono_safer3("ex9_4.wav", &pcm1); 214 | } 215 | 216 | #[allow(non_snake_case)] 217 | fn ex9_5() { 218 | let pcm0_fs = 44100; /* 標本化周波数 */ 219 | let pcm0_length = pcm0_fs * 4; /* 音データの長さ */ 220 | let mut pcm0 = MonoPcm::new16(pcm0_fs, pcm0_length); 221 | 222 | let vco = 440.0; /* 基本周波数 */ 223 | 224 | /* ノコギリ波 */ 225 | let t0 = (pcm0.fs as f64 / vco) as usize; /* 基本周期 */ 226 | let mut m = 0; 227 | for n in 0..pcm0.length { 228 | pcm0.s[n] = 1.0 - 2.0 * m as f64 / t0 as f64; 229 | 230 | m += 1; 231 | if m >= t0 { 232 | m = 0; 233 | } 234 | } 235 | 236 | let vcf = 4000.0; /* 遮断周波数 */ 237 | let Q = 1.0 / 2.0_f64.sqrt(); /* レゾナンス */ 238 | let I = 2; /* 遅延器の数 */ 239 | let J = 2; /* 遅延器の数 */ 240 | let mut a = [0.0; 3]; 241 | let mut b = [0.0; 3]; 242 | safe_IIR_LPF(vcf / pcm0.fs as f64, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 243 | 244 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 245 | 246 | /* フィルタリング */ 247 | for n in 0..pcm1.length { 248 | for m in 0..=J { 249 | if n >= m { 250 | pcm1.s[n] += b[m] * pcm0.s[n - m]; 251 | } 252 | } 253 | for m in 1..=I { 254 | if n >= m { 255 | pcm1.s[n] += -a[m] * pcm1.s[n - m]; 256 | } 257 | } 258 | } 259 | let mut vca = vec![0.0; pcm0.length]; /* 振幅 */ 260 | let gate = pcm1.fs * 3; 261 | let duration = pcm1.fs * 4; 262 | let A = pcm1.fs * 1; 263 | let D = 0; 264 | let S = 1.0; 265 | let R = pcm1.fs * 1; 266 | 267 | safe_ADSR(&mut vca, A, D, S, R, gate, duration); 268 | 269 | let gain = 0.1; /* ゲイン */ 270 | pcm1.mult_varying_gain(&vca, gain); 271 | 272 | /* フェード処理 */ 273 | for n in 0..(pcm1.fs as f64 * 0.01).ceil() as usize { 274 | pcm1.s[n] *= n as f64 / (pcm1.fs as f64 * 0.01); 275 | pcm1.s[pcm1.length - n - 1] *= n as f64 / (pcm1.fs as f64 * 0.01); 276 | } 277 | wave_write_16bit_mono_safer3("ex9_5.wav", &pcm1); 278 | } 279 | 280 | #[allow(non_snake_case)] 281 | fn ex9_6() { 282 | let pcm0_fs = 44100; /* 標本化周波数 */ 283 | let pcm0_length = pcm0_fs * 4; /* 音データの長さ */ 284 | 285 | let mut pcm0 = MonoPcm::new16(pcm0_fs, pcm0_length); 286 | 287 | let vco = 440.0; /* 基本周波数 */ 288 | 289 | /* ノコギリ波 */ 290 | let t0 = (pcm0.fs as f64 / vco) as usize; /* 基本周期 */ 291 | let mut m = 0; 292 | for n in 0..pcm0.length { 293 | pcm0.s[n] = 1.0 - 2.0 * m as f64 / t0 as f64; 294 | 295 | m += 1; 296 | if m >= t0 { 297 | m = 0; 298 | } 299 | } 300 | 301 | let mut vcf = vec![0.0; pcm0.length]; /* 遮断周波数 */ 302 | let gate = pcm0.fs * 1; 303 | let duration = pcm0.fs * 4; 304 | let A = 0; 305 | let D = pcm0.fs * 1; 306 | let S = 0.0; 307 | let R = pcm0.fs * 1; 308 | safe_ADSR(&mut vcf, A, D, S, R, gate, duration); 309 | let offset = 500.0; /* 時間エンベロープのオフセット */ 310 | let depth = 500.0; /* 時間エンベロープのデプス */ 311 | 312 | for n in 0..pcm0.length { 313 | vcf[n] = offset + vcf[n] * depth; 314 | } 315 | let Q = 1.0 / 2.0_f64.sqrt(); /* レゾナンス */ 316 | let I = 2; /* 遅延器の数 */ 317 | let J = 2; /* 遅延器の数 */ 318 | let mut a = [0.0; 3]; 319 | let mut b = [0.0; 3]; 320 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 321 | /* フィルタリング */ 322 | for n in 0..pcm1.length { 323 | safe_IIR_LPF(vcf[n] / pcm1.fs as f64, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 324 | 325 | for m in 0..=J { 326 | if n >= m { 327 | pcm1.s[n] += b[m] * pcm0.s[n - m]; 328 | } 329 | } 330 | for m in 1..=I { 331 | if n >= m { 332 | pcm1.s[n] += -a[m] * pcm1.s[n - m]; 333 | } 334 | } 335 | } 336 | let mut vca = vec![0.0; pcm1.length]; /* 振幅 */ 337 | 338 | let gate = pcm0.fs * 4; 339 | let duration = pcm0.fs * 4; 340 | let A = 0; 341 | let D = pcm0.fs * 4; 342 | let S = 0.0; 343 | let R = pcm0.fs * 1; 344 | safe_ADSR(&mut vca, A, D, S, R, gate, duration); 345 | 346 | let gain = 0.1; /* ゲイン */ 347 | 348 | pcm1.mult_varying_gain(&vca, gain); 349 | 350 | /* フェード処理 */ 351 | for n in 0..(pcm1.fs as f64 * 0.01).ceil() as usize { 352 | pcm1.s[n] *= n as f64 / (pcm1.fs as f64 * 0.01); 353 | pcm1.s[pcm1.length - n - 1] *= n as f64 / (pcm1.fs as f64 * 0.01); 354 | } 355 | wave_write_16bit_mono_safer3("ex9_6.wav", &pcm1); 356 | } 357 | 358 | #[allow(non_snake_case)] 359 | fn ex9_7() { 360 | let pcm0_fs = 44100; /* 標本化周波数 */ 361 | let pcm0_length = pcm0_fs * 1; /* 音データの長さ */ 362 | let mut pcm0 = MonoPcm::new16(pcm0_fs, pcm0_length); 363 | 364 | let mut vco = vec![0.0; pcm0.length]; /* 基本周波数 */ 365 | { 366 | let gate = pcm0.fs * 1; 367 | let duration = pcm0.fs * 1; 368 | let A = 0; 369 | let D = (pcm0.fs as f64 * 0.4) as usize; 370 | let S = 0.0; 371 | let R = (pcm0.fs as f64 * 0.4) as usize; 372 | safe_ADSR(&mut vco, A, D, S, R, gate, duration); 373 | 374 | let offset = 40.0; /* 時間エンベロープのオフセット */ 375 | let depth = 120.0; /* 時間エンベロープのデプス */ 376 | for n in 0..pcm0.length { 377 | vco[n] = vco[n].mul_add(depth, offset); 378 | } 379 | } 380 | { 381 | /* 三角波 */ 382 | let mut t0 = (pcm0.fs as f64 / vco[0]) as usize; /* 基本周期 */ 383 | let mut m = 0; 384 | for n in 0..pcm0.length { 385 | pcm0.s[n] = if (m as f64) < t0 as f64 / 2.0 { 386 | -1.0 + 4.0 * m as f64 / t0 as f64 387 | } else { 388 | 3.0 - 4.0 * m as f64 / t0 as f64 389 | }; 390 | 391 | m += 1; 392 | if m >= t0 { 393 | t0 = (pcm0.fs as f64 / vco[n]) as usize; /* 基本周期 */ 394 | m = 0; 395 | } 396 | } 397 | } 398 | 399 | let mut vcf = vec![0.0; pcm0.length]; /* 遮断周波数 */ 400 | { 401 | let gate = pcm0.fs * 1; 402 | let duration = pcm0.fs * 1; 403 | let A = 0; 404 | let D = (pcm0.fs as f64 * 0.4) as usize; 405 | let S = 0.0; 406 | let R = (pcm0.fs as f64 * 0.4) as usize; 407 | safe_ADSR(&mut vcf, A, D, S, R, gate, duration); 408 | let offset = 80.0; /* 時間エンベロープのオフセット */ 409 | let depth = 240.0; /* 時間エンベロープのデプス */ 410 | for n in 0..pcm0.length { 411 | vcf[n] = vcf[n].mul_add(depth, offset); 412 | } 413 | } 414 | let Q = 5.0; /* レゾナンス */ 415 | let I = 2; /* 遅延器の数 */ 416 | let J = 2; /* 遅延器の数 */ 417 | 418 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 419 | let mut a = [0.0; 3]; 420 | let mut b = [0.0; 3]; 421 | /* フィルタリング */ 422 | for n in 0..pcm1.length { 423 | safe_IIR_LPF(vcf[n] / pcm1.fs as f64, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 424 | 425 | for m in 0..=J { 426 | if n >= m { 427 | pcm1.s[n] += b[m] * pcm0.s[n - m]; 428 | } 429 | } 430 | for m in 1..=I { 431 | if n >= m { 432 | pcm1.s[n] += -a[m] * pcm1.s[n - m]; 433 | } 434 | } 435 | } 436 | 437 | let mut vca = vec![0.0; pcm1.length]; /* 振幅 */ 438 | { 439 | let gate = pcm1.fs * 1; 440 | let duration = pcm1.fs * 1; 441 | let A = 0; 442 | let D = (pcm0.fs as f64 * 0.4) as usize; 443 | let S = 0.0; 444 | let R = (pcm0.fs as f64 * 0.4) as usize; 445 | safe_ADSR(&mut vca, A, D, S, R, gate, duration); 446 | 447 | let gain = 0.9; /* ゲイン */ 448 | pcm1.mult_varying_gain(&vca, gain); 449 | } 450 | /* フェード処理 */ 451 | for n in 0..(pcm1.fs as f64 * 0.01).ceil() as usize { 452 | pcm1.s[n] *= n as f64 / (pcm1.fs as f64 * 0.01); 453 | pcm1.s[pcm1.length - n - 1] *= n as f64 / (pcm1.fs as f64 * 0.01); 454 | } 455 | wave_write_16bit_mono_safer3("ex9_7.wav", &pcm1); 456 | } 457 | 458 | #[allow(non_snake_case)] 459 | fn ex9_8() { 460 | let pcm_fs = 44100; /* 標本化周波数 */ 461 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 462 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 463 | 464 | let vco = 500.0; /* 基本周波数 */ 465 | 466 | /* パルス列 */ 467 | let N = 128; 468 | generate_pulse_sequence(&mut pcm, vco, N); 469 | 470 | let mut s = vec![0.0; pcm.length]; 471 | 472 | /* 積分フィルタ */ 473 | s[0] = pcm.s[0] - 0.5; 474 | for n in 1..pcm.length { 475 | s[n] = s[n - 1].mul_add(0.98, pcm.s[n]); 476 | } 477 | for n in 0..pcm.length { 478 | pcm.s[n] = s[n] * 2.0; 479 | } 480 | 481 | pcm.mult_constant_gain(0.1); 482 | wave_write_16bit_mono_safer3("ex9_8.wav", &pcm); 483 | } 484 | 485 | #[allow(non_snake_case)] 486 | fn ex9_9() { 487 | let pcm_fs = 44100; /* 標本化周波数 */ 488 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 489 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 490 | 491 | let vco = 500.0; /* 基本周波数 */ 492 | 493 | /* 双極性パルス列 */ 494 | let t0 = pcm.fs as f64 / vco; /* 基本周期 */ 495 | let mut t = 0.0; 496 | let mut sign = 1.0; 497 | let N = 128; 498 | while t < pcm.length as f64 { 499 | let ta = t as i32; 500 | 501 | // もともとのコードは 502 | // ``` 503 | // let tb = if t == ta as f64 { ta } else { ta + 1 }; 504 | // ``` 505 | // これは f64 どうしで == を計算している、お行儀の悪いコードである。 506 | // このコードの意図は、t を i32 にしてから f64 に戻した際にもとと一致する(= つまり、小数部分が 0)であるなら t as i32 を、 507 | // さもなければ (t as i32) + 1 を使えということなので、 508 | // つまり切り上げろという意味である。 509 | // したがって、 510 | let tb = t.ceil() as i32; 511 | 512 | for n in (tb - N / 2)..=(ta + N / 2) { 513 | if n >= 0 && n < pcm.length as i32 { 514 | pcm.s[n as usize] += sign 515 | * sinc(PI * (t - n as f64)) 516 | * (2.0 * PI * (t - n as f64) / (N * 2 + 1) as f64) 517 | .cos() 518 | .mul_add(0.5, 0.5); 519 | } 520 | } 521 | 522 | t += t0 / 2.0; 523 | sign *= -1.0; 524 | } 525 | let mut s = vec![0.0; pcm.length]; 526 | 527 | /* 積分フィルタ */ 528 | s[0] = pcm.s[0] - 0.5; 529 | for n in 1..pcm.length { 530 | s[n] = s[n - 1].mul_add(0.98, pcm.s[n]); 531 | } 532 | 533 | for n in 0..pcm.length { 534 | pcm.s[n] = s[n] * 2.0; 535 | } 536 | 537 | pcm.mult_constant_gain(0.1); 538 | wave_write_16bit_mono_safer3("ex9_9.wav", &pcm); 539 | } 540 | 541 | #[allow(non_snake_case)] 542 | fn ex9_10() { 543 | let pcm_fs = 44100; /* 標本化周波数 */ 544 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 545 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 546 | let vco = 500.0; /* 基本周波数 */ 547 | /* 双極性パルス列 */ 548 | let t0 = pcm.fs as f64 / vco; /* 基本周期 */ 549 | let mut t = 0.0; 550 | let mut sign = 1.0; 551 | let N = 128; 552 | 553 | while t < pcm.length as f64 { 554 | let ta = t as i32; 555 | 556 | // もともとのコードは 557 | // ``` 558 | // let tb = if t == ta as f64 { ta } else { ta + 1 }; 559 | // ``` 560 | // これは f64 どうしで == を計算している、お行儀の悪いコードである。 561 | // このコードの意図は、t を i32 にしてから f64 に戻した際にもとと一致する(= つまり、小数部分が 0)であるなら t as i32 を、 562 | // さもなければ (t as i32) + 1 を使えということなので、 563 | // つまり切り上げろという意味である。 564 | // したがって、 565 | let tb = t.ceil() as i32; 566 | 567 | for n in (tb - N / 2)..=(ta + N / 2) { 568 | if n >= 0 && n < pcm.length as i32 { 569 | pcm.s[n as usize] += sign 570 | * sinc(PI * (t - n as f64)) 571 | * (0.5 + 0.5 * (2.0 * PI * (t - n as f64) / (N * 2 + 1) as f64).cos()); 572 | } 573 | } 574 | 575 | t += t0 / 2.0; 576 | sign *= -1.0; 577 | } 578 | let mut s = vec![0.0; pcm.length]; 579 | 580 | /* 積分フィルタ */ 581 | s[0] = pcm.s[0] - 0.5; 582 | for n in 1..pcm.length { 583 | s[n] = s[n - 1].mul_add(0.98, pcm.s[n]); 584 | } 585 | 586 | for n in 0..pcm.length { 587 | pcm.s[n] = s[n] * 2.0; 588 | } 589 | 590 | for n in 0..pcm.length { 591 | pcm.s[n] *= 2.0 / t0; 592 | } 593 | 594 | /* 積分フィルタ */ 595 | s[0] = pcm.s[0] - 0.5; 596 | for n in 1..pcm.length { 597 | s[n] = s[n - 1].mul_add(0.98, pcm.s[n]) ; 598 | } 599 | 600 | for n in 0..pcm.length { 601 | pcm.s[n] = s[n] * 2.0; 602 | } 603 | pcm.mult_constant_gain(0.1); 604 | wave_write_16bit_mono_safer3("ex9_10.wav", &pcm); 605 | } 606 | 607 | #[allow(non_snake_case)] 608 | fn ex9_11() { 609 | let pcm0_fs = 44100; /* 標本化周波数 */ 610 | let pcm0_length = pcm0_fs * 4; /* 音データの長さ */ 611 | let mut pcm0 = MonoPcm::new16(pcm0_fs, pcm0_length); 612 | 613 | let mut s = vec![0.0; pcm0.length]; 614 | let vco = 440.0; /* 基本周波数 */ 615 | 616 | /* パルス列 */ 617 | let N = 128; 618 | generate_pulse_sequence(&mut pcm0, vco, N); 619 | 620 | /* 積分フィルタ */ 621 | s[0] = pcm0.s[0] - 0.5; 622 | for n in 1..pcm0.length { 623 | s[n] = s[n - 1].mul_add(0.98, pcm0.s[n]); 624 | } 625 | 626 | for n in 0..pcm0.length { 627 | pcm0.s[n] = s[n] * 2.0; 628 | } 629 | let vcf = 4000.0; /* 遮断周波数 */ 630 | let Q = 1.0 / 2.0_f64.sqrt(); /* レゾナンス */ 631 | let I = 2; /* 遅延器の数 */ 632 | let J = 2; /* 遅延器の数 */ 633 | let mut a = [0.0; 3]; 634 | let mut b = [0.0; 3]; 635 | safe_IIR_LPF(vcf / pcm0.fs as f64, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 636 | 637 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 638 | /* フィルタリング */ 639 | for n in 0..pcm1.length { 640 | for m in 0..=J { 641 | if n >= m { 642 | pcm1.s[n] += b[m] * pcm0.s[n - m]; 643 | } 644 | } 645 | for m in 1..=I { 646 | if n >= m { 647 | pcm1.s[n] += -a[m] * pcm1.s[n - m]; 648 | } 649 | } 650 | } 651 | 652 | let mut vca = vec![0.0; pcm1.length]; /* 振幅 */ 653 | let gate = pcm1.fs * 3; 654 | let duration = pcm1.fs * 4; 655 | let A = pcm1.fs * 1; 656 | let D = 0; 657 | let S = 1.0; 658 | let R = pcm1.fs * 1; 659 | safe_ADSR(&mut vca, A, D, S, R, gate, duration); 660 | let gain = 0.1; /* ゲイン */ 661 | 662 | pcm1.mult_varying_gain(&vca, gain); 663 | 664 | let pcm2_fs = 44100; /* 標本化周波数 */ 665 | let pcm2_length = pcm2_fs * 4; /* 音データの長さ */ 666 | let mut pcm2 = MonoPcm::new16(pcm2_fs, pcm2_length); 667 | let vco = 440.5; /* 基本周波数 */ 668 | 669 | /* パルス列 */ 670 | generate_pulse_sequence(&mut pcm2, vco, N); 671 | 672 | /* 積分フィルタ */ 673 | s[0] = pcm2.s[0] - 0.5; 674 | for n in 1..pcm2.length { 675 | s[n] = pcm2.s[n] + 0.98 * s[n - 1]; 676 | } 677 | 678 | for n in 0..pcm2.length { 679 | pcm2.s[n] = s[n] * 2.0; 680 | } 681 | 682 | let vcf = 4000.0; /* 遮断周波数 */ 683 | let Q = 1.0 / 2.0f64.sqrt(); /* レゾナンス */ 684 | let I = 2; /* 遅延器の数 */ 685 | let J = 2; /* 遅延器の数 */ 686 | safe_IIR_LPF(vcf / pcm2.fs as f64, Q, &mut a, &mut b); /* IIRフィルタの設計 */ 687 | 688 | let mut pcm3 = MonoPcm::blank_copy(&pcm2); 689 | /* フィルタリング */ 690 | for n in 0..pcm3.length { 691 | for m in 0..=J { 692 | if n >= m { 693 | pcm3.s[n] += b[m] * pcm2.s[n - m]; 694 | } 695 | } 696 | for m in 1..=I { 697 | if n >= m { 698 | pcm3.s[n] += -a[m] * pcm3.s[n - m]; 699 | } 700 | } 701 | } 702 | let mut vca = vec![0.0; pcm3.length]; /* 振幅 */ 703 | let gate = pcm3.fs * 3; 704 | let duration = pcm3.fs * 4; 705 | let A = pcm3.fs * 1; 706 | let D = 0; 707 | let S = 1.0; 708 | let R = pcm3.fs * 1; 709 | safe_ADSR(&mut vca, A, D, S, R, gate, duration); 710 | let gain = 0.1; /* ゲイン */ 711 | 712 | pcm3.mult_varying_gain(&vca, gain); 713 | 714 | /* デチューン */ 715 | for n in 0..pcm3.length { 716 | pcm1.s[n] += pcm3.s[n]; 717 | } 718 | wave_write_16bit_mono_safer3("ex9_11.wav", &pcm1); 719 | } 720 | 721 | #[allow(non_snake_case)] 722 | fn ex10_1() { 723 | let pcm_fs = 44100; /* 標本化周波数 */ 724 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 725 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 726 | let ac = 1.0; /* キャリア振幅 */ 727 | let fc = 500.0; /* キャリア周波数 */ 728 | 729 | let am = 1.0; /* モジュレータ振幅 */ 730 | let ratio = 1.0; /* 周波数比 */ 731 | let fm = fc * ratio; /* モジュレータ周波数 */ 732 | 733 | /* FM音源 */ 734 | for n in 0..pcm.length { 735 | pcm.s[n] = ac 736 | * (2.0 * PI * fc * n as f64 / pcm.fs as f64 737 | + am * (2.0 * PI * fm * n as f64 / pcm.fs as f64).sin()) 738 | .sin(); 739 | } 740 | 741 | pcm.mult_constant_gain(0.1); 742 | wave_write_16bit_mono_safer3("ex10_1.wav", &pcm); 743 | } 744 | 745 | fn ex10_2() { 746 | let pcm_fs = 44100; /* 標本化周波数 */ 747 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 748 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 749 | let ac = 1.0; /* キャリア振幅 */ 750 | let fc = 500.0; /* キャリア周波数 */ 751 | 752 | let am = 1.0; /* モジュレータ振幅 */ 753 | let ratio = 2.0; /* 周波数比 */ 754 | let fm = fc * ratio; /* モジュレータ周波数 */ 755 | /* FM音源 */ 756 | for n in 0..pcm.length { 757 | pcm.s[n] = ac 758 | * (2.0 * PI * fc * n as f64 / pcm.fs as f64 759 | + am * (2.0 * PI * fm * n as f64 / pcm.fs as f64).sin()) 760 | .sin(); 761 | } 762 | pcm.mult_constant_gain(0.1); 763 | wave_write_16bit_mono_safer3("ex10_2.wav", &pcm); 764 | } 765 | 766 | #[allow(non_snake_case)] 767 | fn ex10_3() { 768 | let pcm_fs = 44100; /* 標本化周波数 */ 769 | let pcm_length = pcm_fs * 1; /* 音データの長さ */ 770 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 771 | 772 | let ac = 1.0; /* キャリア振幅 */ 773 | let fc = 500.0; /* キャリア周波数 */ 774 | 775 | let am = 1.0; /* モジュレータ振幅 */ 776 | let ratio = 3.5; /* 周波数比 */ 777 | let fm = fc * ratio; /* モジュレータ周波数 */ 778 | /* FM音源 */ 779 | for n in 0..pcm.length { 780 | pcm.s[n] = ac 781 | * (2.0 * PI * fc * n as f64 / pcm.fs as f64 782 | + am * (2.0 * PI * fm * n as f64 / pcm.fs as f64).sin()) 783 | .sin(); 784 | } 785 | pcm.mult_constant_gain(0.1); 786 | wave_write_16bit_mono_safer3("ex10_3.wav", &pcm); 787 | } 788 | 789 | #[allow(non_snake_case)] 790 | fn ex10_4() { 791 | let pcm_fs = 44100; /* 標本化周波数 */ 792 | let pcm_length = pcm_fs * 4; /* 音データの長さ */ 793 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 794 | 795 | let mut ac: Vec = vec![0.0; pcm_length]; 796 | let mut am: Vec = vec![0.0; pcm_length]; 797 | 798 | /* キャリア振幅 */ 799 | let gate = pcm_fs * 4; 800 | let duration = pcm_fs * 4; 801 | let A = 0; 802 | let D = pcm_fs * 4; 803 | let S = 0.0; 804 | let R = pcm_fs * 4; 805 | safe_ADSR(&mut ac, A, D, S, R, gate, duration); 806 | 807 | let fc = 440.0; /* キャリア周波数 */ 808 | 809 | /* モジュレータ振幅 */ 810 | let gate = pcm_fs * 4; 811 | let duration = pcm_fs * 4; 812 | let A = 0; 813 | let D = pcm_fs * 2; 814 | let S = 0.0; 815 | let R = pcm_fs * 2; 816 | safe_ADSR(&mut am, A, D, S, R, gate, duration); 817 | 818 | let ratio = 3.5; 819 | let fm = fc * ratio; /* モジュレータ周波数 */ 820 | 821 | /* FM音源 */ 822 | for n in 0..pcm_length { 823 | pcm.s[n] = ac[n] 824 | * (2.0 * PI * fc * n as f64 / pcm_fs as f64 825 | + am[n] * (2.0 * PI * fm * n as f64 / pcm_fs as f64).sin()) 826 | .sin(); 827 | } 828 | 829 | pcm.mult_constant_gain(0.1); 830 | 831 | wave_write_16bit_mono_safer3("ex10_4.wav", &pcm); 832 | } 833 | 834 | #[allow(non_snake_case)] 835 | fn ex10_5() { 836 | let pcm0_fs = 44100; /* 標本化周波数 */ 837 | let pcm0_length = pcm0_fs * 4; /* 音データの長さ */ 838 | let mut pcm0 = MonoPcm::new16(pcm0_fs, pcm0_length); 839 | 840 | let mut pcm1 = MonoPcm::blank_copy(&pcm0); 841 | 842 | let mut ac = vec![0.0; pcm0.length]; 843 | let mut am = vec![0.0; pcm0.length]; 844 | { 845 | /* キャリア振幅 */ 846 | let gate = pcm0.fs * 4; 847 | let duration = pcm0.fs * 4; 848 | let A = 0; 849 | let D = pcm0.fs * 4; 850 | let S = 0.0; 851 | let R = pcm0.fs * 1; 852 | safe_ADSR(&mut ac, A, D, S, R, gate, duration); 853 | } 854 | let fc = 440.0; /* キャリア周波数 */ 855 | { 856 | /* モジュレータ振幅 */ 857 | let gate = pcm0.fs * 4; 858 | let duration = pcm0.fs * 4; 859 | let A = 0; 860 | let D = pcm0.fs * 2; 861 | let S = 0.0; 862 | let R = pcm0.fs * 2; 863 | safe_ADSR(&mut am, A, D, S, R, gate, duration); 864 | } 865 | 866 | let ratio = 1.0; 867 | let fm = 440.0 * ratio; /* モジュレータ周波数 */ 868 | /* FM音源 */ 869 | for n in 0..pcm0.length { 870 | pcm0.s[n] = ac[n] 871 | * (2.0 * PI * fc * n as f64 / pcm0.fs as f64 872 | + am[n] * (2.0 * PI * fm * n as f64 / pcm0.fs as f64).sin()) 873 | .sin(); 874 | } 875 | { 876 | /* キャリア振幅 */ 877 | let gate = pcm1.fs * 4; 878 | let duration = pcm1.fs * 4; 879 | let A = 0; 880 | let D = pcm1.fs * 1; 881 | let S = 0.0; 882 | let R = pcm1.fs * 1; 883 | safe_ADSR(&mut ac, A, D, S, R, gate, duration); 884 | } 885 | let fc = 440.0; /* キャリア周波数 */ 886 | { 887 | /* モジュレータ振幅 */ 888 | let gate = pcm1.fs * 4; 889 | let duration = pcm1.fs * 4; 890 | let A = 0; 891 | let D = pcm1.fs * 1; 892 | let S = 0.0; 893 | let R = pcm1.fs * 1; 894 | safe_ADSR(&mut am, A, D, S, R, gate, duration); 895 | } 896 | let ratio = 14.0; 897 | let fm = fc * ratio; /* モジュレータ周波数 */ 898 | /* FM音源 */ 899 | for n in 0..pcm1.length { 900 | pcm1.s[n] = ac[n] 901 | * (2.0 * PI * fc * n as f64 / pcm1.fs as f64 902 | + am[n] * (2.0 * PI * fm * n as f64 / pcm1.fs as f64).sin()) 903 | .sin(); 904 | } 905 | 906 | let gain = 0.1; /* ゲイン */ 907 | 908 | for n in 0..pcm1.length { 909 | pcm1.s[n] += pcm0.s[n]; 910 | pcm1.s[n] *= gain; 911 | } 912 | 913 | wave_write_16bit_mono_safer3("ex10_5.wav", &pcm1); 914 | } 915 | 916 | #[allow(non_snake_case)] 917 | fn ex10_6() { 918 | let pcm_fs = 44100; /* 標本化周波数 */ 919 | let pcm_length = pcm_fs * 4; /* 音データの長さ */ 920 | let mut pcm = MonoPcm::new16(pcm_fs, pcm_length); 921 | 922 | let mut ac = vec![0.0; pcm.length]; 923 | let mut am = vec![0.0; pcm.length]; 924 | 925 | { 926 | /* キャリア振幅 */ 927 | let gate = pcm.fs * 4; 928 | let duration = pcm.fs * 4; 929 | let A = 0; 930 | let D = pcm.fs * 4; 931 | let S = 0.0; 932 | let R = pcm.fs * 4; 933 | safe_ADSR(&mut ac, A, D, S, R, gate, duration); 934 | } 935 | let fc = 440.0; /* キャリア周波数 */ 936 | { 937 | /* モジュレータ振幅 */ 938 | let gate = pcm.fs * 4; 939 | let duration = pcm.fs * 4; 940 | let A = 0; 941 | let D = pcm.fs * 2; 942 | let S = 0.0; 943 | let R = pcm.fs * 2; 944 | safe_ADSR(&mut am, A, D, S, R, gate, duration); 945 | } 946 | let ratio = 3.5; 947 | let fm = fc * ratio; /* モジュレータ周波数 */ 948 | /* AM変調 */ 949 | for n in 0..pcm.length { 950 | pcm.s[n] = ac[n] 951 | * (2.0 * PI * fc * n as f64 / pcm.fs as f64).sin() 952 | * (1.0 + am[n] * (2.0 * PI * fm * n as f64 / pcm.fs as f64).sin()); 953 | } 954 | 955 | pcm.mult_constant_gain(0.1); 956 | 957 | wave_write_16bit_mono_safer3("ex10_6.wav", &pcm); 958 | } 959 | 960 | #[allow(non_snake_case, unused_mut, unused_variables)] 961 | fn ex11_1() { 962 | let pcm0 = wave_read_16bit_mono_safer3("sine_2s.wav"); 963 | let rate = 2.0; 964 | assert!(1.0 < rate); 965 | 966 | let pcm1_fs = pcm0.fs; /* 標本化周波数 */ 967 | let pcm1_length = (pcm0.length as f64 / rate) as usize + 1; /* 音データの長さ */ 968 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); 969 | 970 | let template_size = mult(pcm1.fs, 0.01); /* 相関関数のサイズ */ 971 | let pmin = mult(pcm1.fs, 0.005); /* ピークの探索範囲の下限 */ 972 | let pmax = mult(pcm1.fs, 0.02); /* ピークの探索範囲の上限 */ 973 | 974 | let mut x = vec![0.0; template_size]; 975 | let mut y = vec![0.0; template_size]; 976 | let mut r = vec![0.0; pmax + 1]; 977 | 978 | let mut offset0 = 0; 979 | let mut offset1 = 0; 980 | 981 | while offset0 + pmax * 2 < pcm0.length { 982 | for n in 0..template_size { 983 | x[n] = pcm0.s[offset0 + n]; /* 本来の音データ */ 984 | } 985 | 986 | let mut rmax = 0.0; 987 | let mut p = pmin; 988 | for m in pmin..=pmax { 989 | for n in 0..template_size { 990 | y[n] = pcm0.s[offset0 + m + n]; /* mサンプルずらした音データ */ 991 | } 992 | r[m] = 0.0; 993 | for n in 0..template_size { 994 | r[m] += x[n] * y[n]; /* 相関関数 */ 995 | } 996 | if r[m] > rmax { 997 | rmax = r[m]; /* 相関関数のピーク */ 998 | p = m; /* 波形の周期 */ 999 | } 1000 | } 1001 | 1002 | for n in 0..p { 1003 | pcm1.s[offset1 + n] = pcm0.s[offset0 + n] * (p - n) as f64 / p as f64; /* 単調減少の重みづけ */ 1004 | pcm1.s[offset1 + n] += pcm0.s[offset0 + p + n] * n as f64 / p as f64; 1005 | /* 単調増加の重みづけ */ 1006 | } 1007 | 1008 | let q = (p as f64 / (rate - 1.0) + 0.5) as usize; 1009 | for n in p..q { 1010 | if offset0 + p + n >= pcm0.length { 1011 | break; 1012 | } 1013 | pcm1.s[offset1 + n] = pcm0.s[offset0 + p + n]; 1014 | } 1015 | 1016 | offset0 += p + q; /* offset0の更新 */ 1017 | offset1 += q; /* offset1の更新 */ 1018 | } 1019 | wave_write_16bit_mono_safer3("ex11_1.wav", &pcm1); 1020 | } 1021 | 1022 | #[allow(non_snake_case)] 1023 | fn ex11_2() { 1024 | let pcm0 = wave_read_16bit_mono_safer3("sine_1s.wav"); 1025 | let rate = 0.5; 1026 | assert!(0.5 <= rate && rate < 1.0); 1027 | 1028 | let pcm1_fs = pcm0.fs; /* 標本化周波数 */ 1029 | let pcm1_length = (pcm0.length as f64 / rate) as usize + 1; /* 音データの長さ */ 1030 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); 1031 | 1032 | let template_size = mult(pcm1.fs, 0.01); /* 相関関数のサイズ */ 1033 | let pmin = mult(pcm1.fs, 0.005); /* ピークの探索範囲の下限 */ 1034 | let pmax = mult(pcm1.fs, 0.02); /* ピークの探索範囲の上限 */ 1035 | 1036 | let mut x = vec![0.0; template_size]; 1037 | let mut y = vec![0.0; template_size]; 1038 | let mut r = vec![0.0; pmax + 1]; 1039 | 1040 | let mut offset0 = 0; 1041 | let mut offset1 = 0; 1042 | 1043 | while offset0 + pmax * 2 < pcm0.length { 1044 | for n in 0..template_size { 1045 | x[n] = pcm0.s[offset0 + n]; /* 本来の音データ */ 1046 | } 1047 | 1048 | let mut rmax = 0.0; 1049 | let mut p = pmin; 1050 | for m in pmin..=pmax { 1051 | for n in 0..template_size { 1052 | y[n] = pcm0.s[offset0 + m + n]; /* mサンプルずらした音データ */ 1053 | } 1054 | r[m] = 0.0; 1055 | for n in 0..template_size { 1056 | r[m] += x[n] * y[n]; /* 相関関数 */ 1057 | } 1058 | if r[m] > rmax { 1059 | rmax = r[m]; /* 相関関数のピーク */ 1060 | p = m; /* 波形の周期 */ 1061 | } 1062 | } 1063 | 1064 | for n in 0..p { 1065 | pcm1.s[offset1 + n] = pcm0.s[offset0 + n]; 1066 | } 1067 | for n in 0..p { 1068 | /* 単調減少の重みづけ */ 1069 | pcm1.s[offset1 + p + n] = pcm0.s[offset0 + p + n] * (p - n) as f64 / p as f64; 1070 | 1071 | /* 単調増加の重みづけ */ 1072 | pcm1.s[offset1 + p + n] += pcm0.s[offset0 + n] * n as f64 / p as f64; 1073 | } 1074 | 1075 | let q = (p as f64 * rate / (1.0 - rate) + 0.5) as usize; 1076 | for n in p..q { 1077 | if offset0 + n >= pcm0.length { 1078 | break; 1079 | } 1080 | pcm1.s[offset1 + p + n] = pcm0.s[offset0 + n]; 1081 | } 1082 | 1083 | offset0 += q; /* offset0の更新 */ 1084 | offset1 += p + q; /* offset1の更新 */ 1085 | } 1086 | wave_write_16bit_mono_safer3("ex11_2.wav", &pcm1); 1087 | } 1088 | 1089 | #[allow(non_snake_case)] 1090 | fn ex11_3() { 1091 | let pcm0 = wave_read_16bit_mono_safer3("ex11_sine_500hz.wav"); 1092 | let pitch = 2.0; /* 音の高さを2倍にする */ 1093 | 1094 | let pcm1_fs = pcm0.fs; /* 標本化周波数 */ 1095 | let pcm1_length = (pcm0.length as f64 / pitch) as usize; /* 音データの長さ */ 1096 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); 1097 | 1098 | let N = 128; /* ハニング窓のサイズ */ 1099 | 1100 | Hanning_something(&mut pcm1, &pcm0, pitch, N); 1101 | 1102 | wave_write_16bit_mono_safer3("ex11_3.wav", &pcm1); 1103 | } 1104 | 1105 | #[allow(non_snake_case)] 1106 | fn something(t: f64, n: i32, N: usize) -> f64 { 1107 | sinc(PI * (t - n as f64)) * (0.5 + 0.5 * (2.0 * PI * (t - n as f64) / (N * 2 + 1) as f64).cos()) 1108 | } 1109 | 1110 | #[allow(non_snake_case)] 1111 | fn generate_pulse_sequence(pcm: &mut MonoPcm, vco: f64, N: usize) { 1112 | let t0 = pcm.fs as f64 / vco; /* 基本周期 */ 1113 | let mut t = 0.0; 1114 | while t < pcm.length as f64 { 1115 | let ta = t as usize; 1116 | 1117 | // もともとのコードは 1118 | // ``` 1119 | // let tb = if t == ta as f64 { ta } else { ta + 1 }; 1120 | // ``` 1121 | // これは f64 どうしで == を計算している、お行儀の悪いコードである。 1122 | // このコードの意図は、t を usize にしてから f64 に戻した際にもとと一致する(= つまり、小数部分が 0)であるなら t as usize を、 1123 | // さもなければ (t as usize) + 1 を使えということなので、 1124 | // つまり切り上げろという意味である。 1125 | // したがって、 1126 | let tb = t.ceil() as usize; 1127 | 1128 | for n in (tb as i32 - N as i32 / 2)..=(ta as i32 + N as i32 / 2) { 1129 | if n >= 0 && n < pcm.length as i32 { 1130 | pcm.s[n as usize] += something(t, n, N); 1131 | } 1132 | } 1133 | 1134 | t += t0; 1135 | } 1136 | 1137 | for n in 0..pcm.length { 1138 | pcm.s[n] -= 1.0 / t0 as f64; 1139 | } 1140 | } 1141 | 1142 | #[allow(non_snake_case, unused_mut, unused_variables)] 1143 | fn ex11_4() { 1144 | let pcm0 = wave_read_16bit_mono_safer3("sine_1000hz.wav"); 1145 | let rate = 2.0; 1146 | assert!(1.0 < rate); 1147 | 1148 | let pcm1_fs = pcm0.fs; /* 標本化周波数 */ 1149 | let pcm1_length = (pcm0.length as f64 / rate) as usize + 1; /* 音データの長さ */ 1150 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); 1151 | 1152 | let template_size = mult(pcm1.fs, 0.01); /* 相関関数のサイズ */ 1153 | let pmin = mult(pcm1.fs, 0.005); /* ピークの探索範囲の下限 */ 1154 | let pmax = mult(pcm1.fs, 0.02); /* ピークの探索範囲の上限 */ 1155 | 1156 | let mut x = vec![0.0; template_size]; 1157 | let mut y = vec![0.0; template_size]; 1158 | let mut r = vec![0.0; pmax + 1]; 1159 | 1160 | let mut offset0 = 0; 1161 | let mut offset1 = 0; 1162 | 1163 | while offset0 + pmax * 2 < pcm0.length { 1164 | for n in 0..template_size { 1165 | x[n] = pcm0.s[offset0 + n]; /* 本来の音データ */ 1166 | } 1167 | 1168 | let mut rmax = 0.0; 1169 | let mut p = pmin; 1170 | for m in pmin..=pmax { 1171 | for n in 0..template_size { 1172 | y[n] = pcm0.s[offset0 + m + n]; /* mサンプルずらした音データ */ 1173 | } 1174 | r[m] = 0.0; 1175 | for n in 0..template_size { 1176 | r[m] += x[n] * y[n]; /* 相関関数 */ 1177 | } 1178 | if r[m] > rmax { 1179 | rmax = r[m]; /* 相関関数のピーク */ 1180 | p = m; /* 波形の周期 */ 1181 | } 1182 | } 1183 | 1184 | for n in 0..p { 1185 | pcm1.s[offset1 + n] = pcm0.s[offset0 + n] * (p - n) as f64 / p as f64; /* 単調減少の重み付け */ 1186 | pcm1.s[offset1 + n] += pcm0.s[offset0 + p + n] * n as f64 / p as f64; 1187 | /* 単調増加の重み付け */ 1188 | } 1189 | 1190 | let q = (p as f64 / (rate - 1.0) + 0.5) as usize; 1191 | for n in p..q { 1192 | if offset0 + p + n >= pcm0.length { 1193 | break; 1194 | } 1195 | pcm1.s[offset1 + n] = pcm0.s[offset0 + p + n]; 1196 | } 1197 | 1198 | offset0 += p + q; /* offset0の更新 */ 1199 | offset1 += q; /* offset1の更新 */ 1200 | } 1201 | 1202 | let pitch = 1.0 / rate; 1203 | 1204 | let mut pcm2 = MonoPcm::blank_copy(&pcm0); 1205 | 1206 | let N = 128; /* ハニング窓のサイズ */ 1207 | Hanning_something(&mut pcm2, &pcm1, pitch, N); 1208 | 1209 | wave_write_16bit_mono_safer3("ex11_4.wav", &pcm2); 1210 | } 1211 | 1212 | #[allow(non_snake_case, unused_mut, unused_variables)] 1213 | fn ex11_5() { 1214 | let pcm0 = wave_read_16bit_mono_safer3("ex11_sine_500hz.wav"); 1215 | let rate = 0.5; 1216 | assert!((0.5..1.0).contains(&rate)); 1217 | 1218 | let pcm1_fs = pcm0.fs; /* 標本化周波数 */ 1219 | let pcm1_length = (pcm0.length as f64 / rate) as usize + 1; /* 音データの長さ */ 1220 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); 1221 | 1222 | let template_size = mult(pcm1.fs, 0.01); /* 相関関数のサイズ */ 1223 | let pmin = mult(pcm1.fs, 0.005); /* ピークの探索範囲の下限 */ 1224 | let pmax = mult(pcm1.fs, 0.02); /* ピークの探索範囲の上限 */ 1225 | 1226 | let mut x = vec![0.0; template_size]; 1227 | let mut y = vec![0.0; template_size]; 1228 | let mut r = vec![0.0; pmax + 1]; 1229 | 1230 | let mut offset0 = 0; 1231 | let mut offset1 = 0; 1232 | 1233 | while offset0 + pmax * 2 < pcm0.length { 1234 | /* 本来の音データを書き込む */ 1235 | for n in 0..template_size { 1236 | x[n] = pcm0.s[offset0 + n]; 1237 | } 1238 | 1239 | let mut rmax = 0.0; 1240 | let mut p = pmin; 1241 | for m in pmin..=pmax { 1242 | for n in 0..template_size { 1243 | y[n] = pcm0.s[offset0 + m + n]; /* mサンプルずらした音データ */ 1244 | } 1245 | r[m] = 0.0; 1246 | for n in 0..template_size { 1247 | r[m] += x[n] * y[n]; /* 相関関数 */ 1248 | } 1249 | if r[m] > rmax { 1250 | rmax = r[m]; /* 相関関数のピーク */ 1251 | p = m; /* 波形の周期 */ 1252 | } 1253 | } 1254 | 1255 | for n in 0..p { 1256 | pcm1.s[offset1 + n] = pcm0.s[offset0 + n]; 1257 | } 1258 | for n in 0..p { 1259 | /* 単調減少の重み付け */ 1260 | pcm1.s[offset1 + p + n] = pcm0.s[offset0 + p + n] * (p - n) as f64 / p as f64; 1261 | 1262 | /* 単調増加の重み付け */ 1263 | pcm1.s[offset1 + p + n] += pcm0.s[offset0 + n] * n as f64 / p as f64; 1264 | } 1265 | 1266 | let q = (p as f64 * rate / (1.0 - rate) + 0.5) as usize; 1267 | for n in p..q { 1268 | if offset0 + n >= pcm0.length { 1269 | break; 1270 | } 1271 | pcm1.s[offset1 + p + n] = pcm0.s[offset0 + n]; 1272 | } 1273 | 1274 | offset0 += q; /* offset0の更新 */ 1275 | offset1 += p + q; /* offset1の更新 */ 1276 | } 1277 | 1278 | let pitch = 1.0 / rate; 1279 | let mut pcm2 = MonoPcm::blank_copy(&pcm0); 1280 | let N = 128; /* ハニング窓のサイズ */ 1281 | Hanning_something(&mut pcm2, &pcm1, pitch, N); 1282 | wave_write_16bit_mono_safer3("ex11_5.wav", &pcm2); 1283 | } 1284 | 1285 | #[allow(non_snake_case)] 1286 | fn Hanning_something(pcm1: &mut MonoPcm, pcm0: &MonoPcm, pitch: f64, N: usize) { 1287 | for o in 0..pcm1.length { 1288 | let t = pitch * o as f64; 1289 | let mut tmp = 0.0; 1290 | 1291 | let ta = t as usize; 1292 | 1293 | // もともとのコードは 1294 | // ``` 1295 | // let tb = if t == ta as f64 { ta } else { ta + 1 }; 1296 | // ``` 1297 | // これは f64 どうしで == を計算している、お行儀の悪いコードである。 1298 | // このコードの意図は、t を usize にしてから f64 に戻した際にもとと一致する(= つまり、小数部分が 0)であるなら t as usize を、 1299 | // さもなければ (t as usize) + 1 を使えということなので、 1300 | // つまり切り上げろという意味である。 1301 | // したがって、 1302 | let tb = t.ceil() as usize; 1303 | 1304 | for m in (tb as i32 - N as i32 / 2)..=(ta as i32 + N as i32 / 2) { 1305 | if m >= 0 && m < pcm0.length as i32 { 1306 | tmp += pcm0.s[m as usize] * something(t, m, N); 1307 | } 1308 | } 1309 | 1310 | pcm1.s[o as usize] += tmp; 1311 | } 1312 | } 1313 | 1314 | #[allow(non_snake_case, unused_mut, unused_variables)] 1315 | fn ex11_6() { 1316 | let pcm0 = wave_read_16bit_mono_safer3("vocal.wav"); 1317 | let rate = 0.5; 1318 | assert!((0.5..1.0).contains(&rate)); 1319 | 1320 | let pcm1_fs = pcm0.fs; /* 標本化周波数 */ 1321 | let pcm1_length = (pcm0.length as f64 / rate) as usize + 1; /* 音データの長さ */ 1322 | let mut pcm1 = MonoPcm::new16(pcm1_fs, pcm1_length); 1323 | 1324 | let template_size = mult(pcm1.fs, 0.01); /* 相関関数のサイズ */ 1325 | let pmin = mult(pcm1.fs, 0.005); /* ピークの探索範囲の下限 */ 1326 | let pmax = mult(pcm1.fs, 0.02); /* ピークの探索範囲の上限 */ 1327 | 1328 | let mut x = vec![0.0; template_size]; 1329 | let mut y = vec![0.0; template_size]; 1330 | let mut r = vec![0.0; pmax + 1]; 1331 | 1332 | let mut offset0 = 0; 1333 | let mut offset1 = 0; 1334 | 1335 | while offset0 + pmax * 2 < pcm0.length { 1336 | for n in 0..template_size { 1337 | x[n] = pcm0.s[offset0 + n]; /* 本来の音データ */ 1338 | } 1339 | 1340 | let mut rmax = 0.0; 1341 | let mut p = pmin; 1342 | for m in pmin..=pmax { 1343 | for n in 0..template_size { 1344 | y[n] = pcm0.s[offset0 + m + n]; /* mサンプルずらした音データ */ 1345 | } 1346 | r[m] = 0.0; 1347 | for n in 0..template_size { 1348 | r[m] += x[n] * y[n]; /* 相関関数 */ 1349 | } 1350 | if r[m] > rmax { 1351 | rmax = r[m]; /* 相関関数のピーク */ 1352 | p = m; /* 波形の周期 */ 1353 | } 1354 | } 1355 | 1356 | for n in 0..p { 1357 | pcm1.s[offset1 + n] = pcm0.s[offset0 + n]; 1358 | } 1359 | for n in 0..p { 1360 | /* 単調減少の重み付け */ 1361 | pcm1.s[offset1 + p + n] = pcm0.s[offset0 + p + n] * (p - n) as f64 / p as f64; 1362 | 1363 | /* 単調増加の重み付け */ 1364 | pcm1.s[offset1 + p + n] += pcm0.s[offset0 + n] * n as f64 / p as f64; 1365 | } 1366 | 1367 | let q = (p as f64 * rate / (1.0 - rate) + 0.5) as usize; 1368 | for n in p..q { 1369 | if offset0 + n >= pcm0.length { 1370 | break; 1371 | } 1372 | pcm1.s[offset1 + p + n] = pcm0.s[offset0 + n]; 1373 | } 1374 | 1375 | offset0 += q; /* offset0の更新 */ 1376 | offset1 += p + q; /* offset1の更新 */ 1377 | } 1378 | 1379 | let pitch = 1.0 / rate; 1380 | 1381 | let mut pcm2 = MonoPcm::blank_copy(&pcm0); 1382 | 1383 | let N = 128; 1384 | 1385 | Hanning_something(&mut pcm2, &pcm1, pitch, N); 1386 | 1387 | wave_write_16bit_mono_safer3("ex11_6.wav", &pcm2); 1388 | } 1389 | -------------------------------------------------------------------------------- /sound_programming/synth.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/synth.wav -------------------------------------------------------------------------------- /sound_programming/vocal.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/vocal.wav -------------------------------------------------------------------------------- /sound_programming/wave_utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wave_utils" 3 | version = "0.1.0" 4 | authors = ["hsjoihs "] 5 | 6 | [dependencies] 7 | num-complex = "0.1" 8 | byteorder = "1.2.3" 9 | 10 | -------------------------------------------------------------------------------- /sound_programming/wave_utils/src/fft.rs: -------------------------------------------------------------------------------- 1 | extern crate num_complex; 2 | use self::num_complex::Complex; 3 | use std::f64::consts::PI; 4 | //use libc::c_int; 5 | 6 | fn log2_(x: usize) -> usize { 7 | /* y = log2(x) */ 8 | let mut y = 0; 9 | let mut x = x; 10 | 11 | while x > 1 { 12 | x >>= 1; 13 | y += 1; 14 | } 15 | 16 | return y; 17 | } 18 | 19 | fn pow2(x: usize) -> usize /* y = 2 ^ x */ 20 | { 21 | let y: usize; 22 | 23 | if x == 0 { 24 | y = 1; 25 | } else { 26 | y = 2 << (x - 1); 27 | } 28 | 29 | return y; 30 | } 31 | 32 | #[allow(non_snake_case)] 33 | pub fn safe_FFT_(x: &mut [Complex]) { 34 | let N = x.len(); 35 | let number_of_stage = log2_(N); /* FFTの段数 */ 36 | 37 | /* バタフライ計算 */ 38 | for stage in 1..=number_of_stage { 39 | for i in 0..pow2(stage - 1) { 40 | for j in 0..pow2(number_of_stage - stage) { 41 | let n = pow2(number_of_stage - stage + 1) * i + j; 42 | let m = pow2(number_of_stage - stage) + n; 43 | let r = pow2(stage - 1) * j; 44 | let a = x[n]; 45 | let b = x[m]; 46 | let c = Complex::new(0.0, -(2.0 * PI * r as f64) / N as f64).exp(); 47 | if stage < number_of_stage { 48 | x[n] = a + b; 49 | x[m] = (a - b) * c; 50 | } else { 51 | x[n] = a + b; 52 | x[m] = a - b; 53 | } 54 | } 55 | } 56 | } 57 | 58 | /* インデックスの並び替えのためのテーブルの作成 */ 59 | let mut index: Vec = vec![0; N]; 60 | for stage in 1..=number_of_stage { 61 | for i in 0..pow2(stage - 1) { 62 | index[pow2(stage - 1) + i] = index[i] + pow2(number_of_stage - stage); 63 | } 64 | } 65 | 66 | /* インデックスの並び替え */ 67 | for k in 0..N { 68 | if index[k] > k { 69 | let tmp = x[index[k]]; 70 | x[index[k]] = x[k]; 71 | x[k] = tmp; 72 | } 73 | } 74 | } 75 | 76 | #[allow(unused_variables, non_snake_case)] 77 | pub fn safe_IFFT_(x: &mut [Complex]) { 78 | let N = x.len(); 79 | 80 | let number_of_stage = log2_(N); /* IFFTの段数 */ 81 | 82 | /* バタフライ計算 */ 83 | for stage in 1..=number_of_stage { 84 | for i in 0..pow2(stage - 1) { 85 | for j in 0..pow2(number_of_stage - stage) { 86 | let n = pow2(number_of_stage - stage + 1) * i + j; 87 | let m = pow2(number_of_stage - stage) + n; 88 | let r = pow2(stage - 1) * j; 89 | let a = x[n]; 90 | let b = x[m]; 91 | let c = Complex::new(0.0, (2.0 * PI * r as f64) / N as f64).exp(); 92 | 93 | if stage < number_of_stage { 94 | x[n] = a + b; 95 | x[m] = (a - b) * c; 96 | } else { 97 | x[n] = a + b; 98 | x[m] = a - b; 99 | } 100 | } 101 | } 102 | } 103 | 104 | /* インデックスの並び替えのためのテーブルの作成 */ 105 | let mut index: Vec = vec![0; N]; 106 | for stage in 1..=number_of_stage { 107 | for i in 0..pow2(stage - 1) { 108 | index[pow2(stage - 1) + i] = index[i] + pow2(number_of_stage - stage); 109 | } 110 | } 111 | 112 | /* インデックスの並び替え */ 113 | for k in 0..N { 114 | if index[k] > k { 115 | let tmp = x[index[k]]; 116 | x[index[k]] = x[k]; 117 | x[k] = tmp; 118 | } 119 | } 120 | 121 | /* 計算結果をNで割る */ 122 | for k in 0..N { 123 | x[k].re /= N as f64; 124 | x[k].im /= N as f64; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /sound_programming/wave_utils/src/filter.rs: -------------------------------------------------------------------------------- 1 | use sinc; 2 | use std::f64::consts::PI; 3 | 4 | /*#[allow(non_snake_case)] 5 | pub fn safe_FIR_LPF(fe: f64, J: usize, b: &mut [f64], w: &[f64]) { 6 | assert_eq!(J % 2, 0); 7 | assert_eq!(J + 1, b.len()); 8 | assert_eq!(J + 1, w.len()); 9 | 10 | // k = m + J/2 11 | for (k, item) in b.iter_mut().enumerate() { 12 | let m = k as f64 - (J/2) as f64; 13 | *item = 2.0 * fe * sinc(2.0 * PI * fe * m); 14 | } 15 | 16 | for (m, item) in b.iter_mut().enumerate() { 17 | *item *= w[m]; 18 | } 19 | }*/ 20 | 21 | #[allow(non_snake_case)] 22 | pub fn get_FIR_LPF(fe: f64, J: usize, w: &[f64])-> Vec { 23 | assert_eq!(J % 2, 0); 24 | assert_eq!(J + 1, w.len()); 25 | 26 | (0..=J).map(|k| { 27 | let m = k as f64 - (J/2) as f64; 28 | (2.0 * fe * sinc(2.0 * PI * fe * m)) * w[k] 29 | }).collect() 30 | } 31 | 32 | #[allow(non_snake_case)] 33 | pub fn safe_FIR_filtering(x: &[f64], y: &mut [f64], L: usize, b: &[f64], J: usize) { 34 | // check index here 35 | assert_eq!(J + 1, b.len()); 36 | 37 | for n in 0..L { 38 | for m in 0..=J { 39 | if n >= m { 40 | y[n] += b[m] * x[n - m]; 41 | } 42 | } 43 | } 44 | } 45 | 46 | // not tested 47 | #[allow(non_snake_case)] 48 | pub fn safe_FIR_HPF(fe: f64, J: usize, b: &mut [f64], w: &[f64]) { 49 | assert_eq!(J % 2, 0); 50 | assert_eq!(J + 1, b.len()); 51 | assert_eq!(J + 1, w.len()); 52 | // k = m + J/2 53 | for (k, item) in b.iter_mut().enumerate() { 54 | let m = k as f64 - (J/2) as f64; 55 | *item = sinc(PI * m) 56 | - 2.0 * fe * sinc(2.0 * PI * fe * m); 57 | } 58 | 59 | for m in 0..(J + 1) as usize { 60 | b[m] *= w[m]; 61 | } 62 | } 63 | 64 | // not tested 65 | #[allow(non_snake_case)] 66 | pub fn safe_FIR_BPF(fe1: f64, fe2: f64, J: usize, b: &mut [f64], w: &[f64]) { 67 | assert_eq!(J % 2, 0); 68 | assert_eq!(J + 1, b.len()); 69 | assert_eq!(J + 1, w.len()); 70 | // k = m + J/2 71 | for (k, item) in b.iter_mut().enumerate() { 72 | let m = k as f64 - (J/2) as f64; 73 | *item = 2.0 * fe2 * sinc(2.0 * PI * fe2 * m) 74 | - 2.0 * fe1 * sinc(2.0 * PI * fe1 * m); 75 | } 76 | 77 | for m in 0..(J + 1) as usize { 78 | b[m] *= w[m]; 79 | } 80 | } 81 | 82 | // not tested 83 | #[allow(non_snake_case)] 84 | pub fn safe_FIR_BEF(fe1: f64, fe2: f64, J: usize, b: &mut [f64], w: &[f64]) { 85 | assert_eq!(J % 2, 0); 86 | assert_eq!(J + 1, b.len()); 87 | assert_eq!(J + 1, w.len()); 88 | // k = m + J/2 89 | for (k, item) in b.iter_mut().enumerate() { 90 | let m = k as f64 - (J/2) as f64; 91 | *item = sinc(PI * m) - 2.0 * fe2 * sinc(2.0 * PI * fe2 * m) 92 | + 2.0 * fe1 * sinc(2.0 * PI * fe1 * m); 93 | } 94 | 95 | for m in 0..(J + 1) as usize { 96 | b[m] *= w[m]; 97 | } 98 | } 99 | 100 | //not tested 101 | #[allow(non_snake_case)] 102 | pub fn safe_IIR_HPF(fc: f64, Q: f64, a: &mut [f64], b: &mut [f64]) { 103 | assert_eq!(3, a.len()); 104 | assert_eq!(3, b.len()); 105 | let fc = (PI * fc).tan() / (2.0 * PI); 106 | a[0] = 1.0 + 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc; 107 | a[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 108 | a[2] = (1.0 - 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 109 | b[0] = 1.0 / a[0]; 110 | b[1] = -2.0 / a[0]; 111 | b[2] = 1.0 / a[0]; 112 | 113 | a[0] = 1.0; 114 | } 115 | 116 | //not tested 117 | #[allow(non_snake_case)] 118 | pub fn safe_IIR_BPF(fc1: f64, fc2: f64, a: &mut [f64], b: &mut [f64]) { 119 | assert_eq!(3, a.len()); 120 | assert_eq!(3, b.len()); 121 | let fc1 = (PI * fc1).tan() / (2.0 * PI); 122 | let fc2 = (PI * fc2).tan() / (2.0 * PI); 123 | a[0] = 1.0 + 2.0 * PI * (fc2 - fc1) + 4.0 * PI * PI * fc1 * fc2; 124 | a[1] = (8.0 * PI * PI * fc1 * fc2 - 2.0) / a[0]; 125 | a[2] = (1.0 - 2.0 * PI * (fc2 - fc1) + 4.0 * PI * PI * fc1 * fc2) / a[0]; 126 | b[0] = 2.0 * PI * (fc2 - fc1) / a[0]; 127 | b[1] = 0.0; 128 | b[2] = -2.0 * PI * (fc2 - fc1) / a[0]; 129 | 130 | a[0] = 1.0; 131 | } 132 | 133 | //not tested 134 | #[allow(non_snake_case)] 135 | pub fn safe_IIR_BEF(fc1: f64, fc2: f64, a: &mut [f64], b: &mut [f64]) { 136 | assert_eq!(3, a.len()); 137 | assert_eq!(3, b.len()); 138 | let fc1 = (PI * fc1).tan() / (2.0 * PI); 139 | let fc2 = (PI * fc2).tan() / (2.0 * PI); 140 | 141 | a[0] = 1.0 + 2.0 * PI * (fc2 - fc1) + 4.0 * PI * PI * fc1 * fc2; 142 | a[1] = (8.0 * PI * PI * fc1 * fc2 - 2.0) / a[0]; 143 | a[2] = (1.0 - 2.0 * PI * (fc2 - fc1) + 4.0 * PI * PI * fc1 * fc2) / a[0]; 144 | b[0] = (4.0 * PI * PI * fc1 * fc2 + 1.0) / a[0]; 145 | b[1] = (8.0 * PI * PI * fc1 * fc2 - 2.0) / a[0]; 146 | b[2] = (4.0 * PI * PI * fc1 * fc2 + 1.0) / a[0]; 147 | 148 | a[0] = 1.0; 149 | } 150 | 151 | //not tested 152 | #[allow(non_snake_case)] 153 | pub fn safe_IIR_notch(fc: f64, Q: f64, a: &mut [f64], b: &mut [f64]) { 154 | assert_eq!(3, a.len()); 155 | assert_eq!(3, b.len()); 156 | let fc = (PI * fc).tan() / (2.0 * PI); 157 | a[0] = 1.0 + 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc; 158 | a[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 159 | a[2] = (1.0 - 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 160 | b[0] = (4.0 * PI * PI * fc * fc + 1.0) / a[0]; 161 | b[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 162 | b[2] = (4.0 * PI * PI * fc * fc + 1.0) / a[0]; 163 | 164 | a[0] = 1.0; 165 | } 166 | 167 | //not tested 168 | #[allow(non_snake_case)] 169 | pub fn safe_IIR_low_shelving(fc: f64, Q: f64, g: f64, a: &mut [f64], b: &mut [f64]) { 170 | assert_eq!(3, a.len()); 171 | assert_eq!(3, b.len()); 172 | let fc = (PI * fc).tan() / (2.0 * PI); 173 | a[0] = 1.0 + 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc; 174 | a[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 175 | a[2] = (1.0 - 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 176 | b[0] = 177 | (1.0 + (1.0 + g).sqrt() * 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc * (1.0 + g)) / a[0]; 178 | b[1] = (8.0 * PI * PI * fc * fc * (1.0 + g) - 2.0) / a[0]; 179 | b[2] = 180 | (1.0 - (1.0 + g).sqrt() * 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc * (1.0 + g)) / a[0]; 181 | 182 | a[0] = 1.0; 183 | } 184 | 185 | //not tested 186 | #[allow(non_snake_case)] 187 | pub fn safe_IIR_high_shelving(fc: f64, Q: f64, g: f64, a: &mut [f64], b: &mut [f64]) { 188 | assert_eq!(3, a.len()); 189 | assert_eq!(3, b.len()); 190 | let fc = (PI * fc).tan() / (2.0 * PI); 191 | a[0] = 1.0 + 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc; 192 | a[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 193 | a[2] = (1.0 - 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 194 | b[0] = ((1.0 + g) + (1.0 + g).sqrt() * 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 195 | b[1] = (8.0 * PI * PI * fc * fc - 2.0 * (1.0 + g)) / a[0]; 196 | b[2] = ((1.0 + g) - (1.0 + g).sqrt() * 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 197 | 198 | a[0] = 1.0; 199 | } 200 | 201 | //not tested 202 | #[allow(non_snake_case)] 203 | pub fn safe_IIR_peaking(fc: f64, Q: f64, g: f64, a: &mut [f64], b: &mut [f64]) { 204 | assert_eq!(3, a.len()); 205 | assert_eq!(3, b.len()); 206 | let fc = (PI * fc).tan() / (2.0 * PI); 207 | a[0] = 1.0 + 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc; 208 | a[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 209 | a[2] = (1.0 - 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 210 | b[0] = (1.0 + 2.0 * PI * fc / Q * (1.0 + g) + 4.0 * PI * PI * fc * fc) / a[0]; 211 | b[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 212 | b[2] = (1.0 - 2.0 * PI * fc / Q * (1.0 + g) + 4.0 * PI * PI * fc * fc) / a[0]; 213 | 214 | a[0] = 1.0; 215 | } 216 | 217 | #[allow(non_snake_case)] 218 | pub fn safe_IIR_LPF(fc: f64, Q: f64, a: &mut [f64], b: &mut [f64]) { 219 | assert_eq!(3, a.len()); 220 | assert_eq!(3, b.len()); 221 | let fc = (PI * fc).tan() / (2.0 * PI); 222 | 223 | a[0] = 1.0 + 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc; 224 | a[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 225 | a[2] = (1.0 - 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 226 | b[0] = 4.0 * PI * PI * fc * fc / a[0]; 227 | b[1] = 8.0 * PI * PI * fc * fc / a[0]; 228 | b[2] = 4.0 * PI * PI * fc * fc / a[0]; 229 | 230 | a[0] = 1.0; 231 | } 232 | 233 | #[allow(non_snake_case)] 234 | pub fn safe_IIR_filtering( 235 | x: &[f64], 236 | y: &mut [f64], 237 | L: usize, 238 | a: &[f64], 239 | b: &[f64], 240 | I: usize, 241 | J: usize, 242 | ) { 243 | assert_eq!(J + 1, b.len()); 244 | assert_eq!(I + 1, a.len()); 245 | assert_eq!(L, x.len()); 246 | assert_eq!(L, y.len()); 247 | 248 | for n in 0..L { 249 | for m in 0..=J { 250 | if n >= m { 251 | y[n] += b[m] * x[n - m]; 252 | } 253 | } 254 | for m in 1..=I { 255 | if n >= m { 256 | y[n] += -a[m] * y[n - m]; 257 | } 258 | } 259 | } 260 | } 261 | 262 | #[allow(non_snake_case)] 263 | pub fn safe_IIR_resonator(fc: f64, Q: f64, a: &mut [f64], b: &mut [f64]) { 264 | assert_eq!(3, a.len()); 265 | assert_eq!(3, b.len()); 266 | let fc = (PI * fc).tan() / (2.0 * PI); 267 | 268 | a[0] = 1.0 + 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc; 269 | a[1] = (8.0 * PI * PI * fc * fc - 2.0) / a[0]; 270 | a[2] = (1.0 - 2.0 * PI * fc / Q + 4.0 * PI * PI * fc * fc) / a[0]; 271 | b[0] = 2.0 * PI * fc / Q / a[0]; 272 | b[1] = 0.0; 273 | b[2] = -2.0 * PI * fc / Q / a[0]; 274 | 275 | a[0] = 1.0; 276 | } 277 | -------------------------------------------------------------------------------- /sound_programming/wave_utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod fft; 2 | pub mod filter; 3 | use std::f64::consts::PI; 4 | pub mod wave; 5 | 6 | #[allow(non_snake_case)] 7 | pub fn safe_ADSR( 8 | e: &mut [f64], 9 | A: usize, 10 | D: usize, 11 | S: f64, 12 | R: usize, 13 | gate: usize, 14 | duration: usize, 15 | ) { 16 | if A != 0 { 17 | for n in 0..A { 18 | e[n] = 1.0 - (-5.0 * n as f64 / A as f64).exp(); 19 | } 20 | } 21 | 22 | if D != 0 { 23 | for n in A..gate { 24 | e[n] = S + (1.0 - S) * (-5.0 * (n - A) as f64 / D as f64).exp(); 25 | } 26 | } else { 27 | for n in A..gate { 28 | e[n] = S; 29 | } 30 | } 31 | 32 | if R != 0 { 33 | for n in gate..duration { 34 | e[n] = e[gate - 1] * (-5.0 * (n - gate + 1) as f64 / R as f64).exp(); 35 | } 36 | } 37 | } 38 | 39 | #[derive(Clone)] 40 | pub struct MonoPcm { 41 | pub fs: usize, 42 | pub bits: i32, 43 | pub length: usize, 44 | pub s: Vec, 45 | } 46 | 47 | impl MonoPcm { 48 | pub fn new16(fs: usize, length: usize) -> Self { 49 | MonoPcm { 50 | fs, 51 | length, 52 | bits: 16, 53 | s: vec![0.0; length], 54 | } 55 | } 56 | pub fn blank_copy(orig: &Self) -> Self { 57 | MonoPcm { 58 | s: vec![0.0; orig.length as usize], 59 | ..*orig 60 | } 61 | } 62 | 63 | pub fn mult_constant_gain(&mut self, gain: f64) { 64 | for n in 0..self.length { 65 | self.s[n] *= gain; 66 | } 67 | } 68 | 69 | pub fn mult_varying_gain(&mut self, vec: &[f64], gain: f64) { 70 | assert!(vec.len() >= self.length); 71 | for n in 0..self.length { 72 | self.s[n] *= vec[n] * gain 73 | } 74 | } 75 | 76 | pub fn new16_fn(fs: usize, length: usize, mut fun: Box f64>) -> Self { 77 | MonoPcm { 78 | fs, 79 | length, 80 | bits: 16, 81 | s: (0..length).map(|n| fun(n)).collect(), 82 | } 83 | } 84 | 85 | pub fn new16_sawtooth_with_varying_freq(fs: usize, length: usize, f0: &[f64]) -> Self { 86 | MonoPcm{ 87 | fs, 88 | length, 89 | bits: 16, 90 | s: sawtooth_with_varying_freq(fs, length, f0) 91 | } 92 | } 93 | } 94 | 95 | pub fn linear(initial_v: f64, final_v: f64, length: usize) -> Vec { 96 | (0..length) 97 | .map(|n| initial_v + (final_v - initial_v) * n as f64 / (length - 1) as f64) 98 | .collect() 99 | } 100 | 101 | pub fn sawtooth_with_varying_freq(pcm0_fs: usize, pcm0_length: usize, f0: &[f64]) -> Vec { 102 | assert!(f0.len() >= pcm0_length); 103 | let mut pcm0_s = vec![0.0; pcm0_length]; 104 | 105 | /* ノコギリ波 */ 106 | let mut t0 = (pcm0_fs as f64 / f0[0]) as usize; /* 基本周期 */ 107 | let mut m = 0; 108 | for n in 0..pcm0_length { 109 | pcm0_s[n] = 1.0 - 2.0 * m as f64 / t0 as f64; 110 | 111 | m += 1; 112 | if m >= t0 { 113 | t0 = (pcm0_fs as f64 / f0[n]) as usize; /* 基本周期 */ 114 | m = 0; 115 | } 116 | } 117 | pcm0_s 118 | } 119 | 120 | #[derive(Clone)] 121 | pub struct StereoPcm { 122 | pub fs: usize, 123 | pub bits: i32, 124 | pub length: usize, 125 | pub s_l: Vec, 126 | pub s_r: Vec, 127 | } 128 | 129 | #[allow(non_snake_case)] 130 | pub fn create_Hanning_window(N: usize) -> Vec { 131 | (0..N) 132 | .map(|n| { 133 | 0.5 - 0.5 * (2.0 * PI * (n as f64 + if N % 2 == 0 { 0.0 } else { 0.5 }) / (N as f64)) 134 | .cos() 135 | }) 136 | .collect() 137 | } 138 | 139 | pub fn sinc(x: f64) -> f64 { 140 | if x == 0.0 { 141 | 1.0 142 | } else { 143 | x.sin() / x 144 | } 145 | } 146 | 147 | #[allow(non_snake_case)] 148 | pub fn determine_J(delta: f64) -> usize { 149 | let mut J = (3.1 / delta + 0.5) as usize - 1; /* 遅延器の数 */ 150 | if J % 2 == 1 { 151 | J += 1; /* J+1が奇数になるように調整する */ 152 | } 153 | return J; 154 | } 155 | 156 | pub fn lfo( 157 | pcm: &MonoPcm, 158 | center: f64, 159 | am: f64, /* LFOの振幅 */ 160 | fm: f64, /* LFOの周波数 */ 161 | ) -> Vec { 162 | (0..pcm.length) 163 | .map(|n| center + am * (2.0 * PI * fm * n as f64 / pcm.fs as f64).sin()) 164 | .collect() 165 | } 166 | 167 | pub fn mult(i: usize, d: f64) -> usize { 168 | ((i as f64) * d) as usize 169 | } 170 | -------------------------------------------------------------------------------- /sound_programming/wave_utils/src/wave/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate byteorder; 2 | use self::byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; 3 | use MonoPcm; 4 | use StereoPcm; 5 | use wave::read::read_i8x4; 6 | use wave::read::read_partial_header; 7 | use wave::read::read_u8x4; 8 | use wave::write::Pcm; 9 | use wave::write::wave_write_header; 10 | use wave::write::wave_write_header_partial; 11 | use wave::write::write_i8x4; 12 | use wave::write::write_u8x4; 13 | 14 | mod read; 15 | mod write; 16 | 17 | pub fn wave_read_8bit_mono_safer3(path: &str) -> MonoPcm { 18 | let (mut fp, pcm_fs, pcm_bits, data_chunk_size) = read::read_header(path); 19 | let pcm_length = data_chunk_size as usize; 20 | let mut pcm_s = vec![0.0; pcm_length]; 21 | 22 | for n in 0..pcm_length { 23 | let data = fp.read_u8().unwrap(); 24 | pcm_s[n] = data.convert_to_float(); /* 音データを-1以上1未満の範囲に正規化する */ 25 | } 26 | 27 | return MonoPcm { 28 | s: pcm_s, 29 | fs: pcm_fs as usize, 30 | bits: pcm_bits as i32, 31 | length: pcm_length as usize, 32 | }; 33 | } 34 | 35 | #[allow(non_snake_case)] 36 | pub fn wave_read_8bit_stereo_safer3(path: &str) -> StereoPcm { 37 | let (mut fp, pcm_fs, pcm_bits, data_chunk_size) = read::read_header(path); 38 | let pcm_length = (data_chunk_size / 2) as usize; /* 音データの長さ */ 39 | 40 | let mut pcm_sL = vec![0.0; pcm_length]; 41 | let mut pcm_sR = vec![0.0; pcm_length]; 42 | for n in 0..pcm_length { 43 | let data = fp.read_u8().unwrap(); 44 | pcm_sL[n] = data.convert_to_float(); /* 音データを-1以上1未満の範囲に正規化する */ 45 | let data = fp.read_u8().unwrap(); 46 | pcm_sR[n] = data.convert_to_float(); /* 音データを-1以上1未満の範囲に正規化する */ 47 | } 48 | return StereoPcm { 49 | s_l: pcm_sL, 50 | s_r: pcm_sR, 51 | fs: pcm_fs as usize, 52 | bits: pcm_bits as i32, 53 | length: pcm_length as usize, 54 | }; 55 | } 56 | 57 | pub fn wave_read_16bit_mono_safer3(path: &str) -> MonoPcm { 58 | let (mut fp, pcm_fs, pcm_bits, data_chunk_size) = read::read_header(path); 59 | let pcm_length = (data_chunk_size / 2) as usize; 60 | let mut pcm_s = vec![0.0; pcm_length]; 61 | 62 | for n in 0..pcm_length { 63 | let data = fp.read_i16::().unwrap(); 64 | pcm_s[n] = data.convert_to_float(); /* 音データを-1以上1未満の範囲に正規化する */ 65 | } 66 | 67 | return MonoPcm { 68 | s: pcm_s, 69 | fs: pcm_fs as usize, 70 | bits: pcm_bits as i32, 71 | length: pcm_length as usize, 72 | }; 73 | } 74 | 75 | #[allow(non_snake_case)] 76 | pub fn wave_read_16bit_stereo_safer3(path: &str) -> StereoPcm { 77 | let (mut fp, pcm_fs, pcm_bits, data_chunk_size) = read::read_header(path); 78 | let pcm_length = (data_chunk_size / 4) as usize; /* 音データの長さ */ 79 | 80 | let mut pcm_sL = vec![0.0; pcm_length]; 81 | let mut pcm_sR = vec![0.0; pcm_length]; 82 | for n in 0..pcm_length { 83 | let data = fp.read_i16::().unwrap(); 84 | pcm_sL[n] = data.convert_to_float(); /* 音データを-1以上1未満の範囲に正規化する */ 85 | let data = fp.read_i16::().unwrap(); 86 | pcm_sR[n] = data.convert_to_float(); /* 音データを-1以上1未満の範囲に正規化する */ 87 | } 88 | 89 | return StereoPcm { 90 | s_l: pcm_sL, 91 | s_r: pcm_sR, 92 | fs: pcm_fs as usize, 93 | bits: pcm_bits as i32, 94 | length: pcm_length as usize, 95 | }; 96 | } 97 | 98 | #[allow(non_upper_case_globals)] 99 | const step_size_table: [i32; 89] = [ 100 | 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 101 | 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 102 | 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 103 | 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 104 | 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767, 105 | ]; 106 | 107 | #[allow(non_upper_case_globals)] 108 | const index_table: [i32; 16] = [-1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8]; 109 | 110 | #[allow(non_snake_case)] 111 | pub fn wave_read_IMA_ADPCM_mono_safer3(path: &str) -> MonoPcm { 112 | let (mut fp, samples_per_sec, block_size, _bits_per_sample) = read_partial_header(path); 113 | 114 | { 115 | let extra_size = fp.read_i16::().unwrap(); 116 | assert_eq!(extra_size, 2); 117 | } 118 | let samples_per_block = fp.read_i16::().unwrap(); 119 | { 120 | let fact_chunk_ID = read_i8x4(&mut fp); 121 | assert_eq!(fact_chunk_ID, ['f' as i8, 'a' as i8, 'c' as i8, 't' as i8]); 122 | } 123 | let _fact_chunk_size = fp.read_i32::().unwrap(); 124 | let sample_length = fp.read_i32::().unwrap(); 125 | 126 | { 127 | let data_chunk_ID = read_i8x4(&mut fp); 128 | assert_eq!(data_chunk_ID, ['d' as i8, 'a' as i8, 't' as i8, 'a' as i8]); 129 | } 130 | let data_chunk_size = fp.read_i32::().unwrap(); 131 | 132 | let number_of_block: i32 = data_chunk_size / block_size as i32; 133 | 134 | let pcm_fs = samples_per_sec; /* 標本化周波数 */ 135 | let pcm_length = sample_length; /* 音データの長さ */ 136 | let mut pcm_s = vec![0.0; pcm_length as usize]; /* メモリの確保 */ 137 | 138 | for block in 0..number_of_block { 139 | let mut s: i16; 140 | let mut index: i32 = 0; 141 | let offset: i32 = samples_per_block as i32 * block as i32; 142 | let mut data: u8 = 0; 143 | let mut sp: i32 = 0; 144 | for n in 0..samples_per_block { 145 | if n == 0 { 146 | let header = read_u8x4(&mut fp); 147 | sp = (((header[1] as i8) as i16) << 8) as i32 + header[0] as i32; 148 | index = header[2] as i32; 149 | s = sp as i16; 150 | } else { 151 | /* 4bitの圧縮データ */ 152 | let c: u8 = if (n % 2) == 1 { 153 | data = fp.read_u8().unwrap(); /* 圧縮データの読み取り */ 154 | 155 | (data & 0x0F) as u8 /* dataの下位4bit */ 156 | } else { 157 | ((data >> 4) & 0x0F) as u8 /* dataの上位4bit */ 158 | }; 159 | 160 | let step_size: i32 = step_size_table[index as usize]; 161 | 162 | /* 伸張 */ 163 | let mut dp: i32 = step_size >> 3; 164 | if (c & 0x1) == 0x1 { 165 | dp += step_size >> 2; 166 | } 167 | if (c & 0x2) == 0x2 { 168 | dp += step_size >> 1; 169 | } 170 | if (c & 0x4) == 0x4 { 171 | dp += step_size; 172 | } 173 | if (c & 0x8) == 0x8 { 174 | sp -= dp; 175 | } else { 176 | sp += dp; 177 | } 178 | 179 | if sp > 32767 { 180 | sp = 32767; 181 | } else if sp < -32768 { 182 | sp = -32768; 183 | } 184 | 185 | index += index_table[c as usize]; 186 | 187 | if index < 0 { 188 | index = 0; 189 | } else if index > 88 { 190 | index = 88; 191 | } 192 | 193 | s = sp as i16; 194 | } 195 | 196 | pcm_s[offset as usize + n as usize] = s as f64 / 32768.0; /* 音データを-1以上1未満の範囲に正規化する */ 197 | } 198 | } 199 | 200 | MonoPcm { 201 | fs: pcm_fs as usize, 202 | bits: 16, 203 | length: pcm_length as usize, 204 | s: pcm_s, 205 | } 206 | } 207 | 208 | #[allow(non_snake_case)] 209 | pub fn wave_write_IMA_ADPCM_mono_safer3(path: &str, pcm: &MonoPcm) { 210 | let block_size: i16 = 256; 211 | let samples_per_block: i16 = (block_size - 4) * 2 + 1; 212 | let number_of_block: i32 = (pcm.length / samples_per_block as usize) as i32; 213 | 214 | let mut fp = wave_write_header_partial( 215 | path, 216 | 52, 217 | block_size as i32 * number_of_block, 218 | 20, 219 | 17, 220 | 1, 221 | pcm.fs, 222 | block_size as i32 * pcm.fs as i32 / samples_per_block as i32, 223 | block_size, 224 | 4, 225 | ); 226 | 227 | let extra_size: i16 = 2; 228 | let fact_chunk_ID: [i8; 4] = ['f' as i8, 'a' as i8, 'c' as i8, 't' as i8]; 229 | let fact_chunk_size: i32 = 4; 230 | let sample_length: i32 = samples_per_block as i32 * number_of_block as i32 + 1; 231 | 232 | fp.write_i16::(extra_size).unwrap(); 233 | fp.write_i16::(samples_per_block).unwrap(); 234 | write_i8x4(&mut fp, fact_chunk_ID); 235 | fp.write_i32::(fact_chunk_size).unwrap(); 236 | fp.write_i32::(sample_length).unwrap(); 237 | 238 | let data_chunk_ID: [i8; 4] = ['d' as i8, 'a' as i8, 't' as i8, 'a' as i8]; 239 | write_i8x4(&mut fp, data_chunk_ID); 240 | let data_chunk_size: i32 = block_size as i32 * number_of_block as i32; 241 | fp.write_i32::(data_chunk_size).unwrap(); 242 | 243 | let mut sp: i32 = 0; 244 | let mut d: i32; 245 | let mut dp: i32; 246 | let mut index: i32 = 0; 247 | let mut step_size: i32; 248 | let mut x: f64; 249 | let mut s: i16; /* 16bitの音データ */ 250 | let mut header: [u8; 4] = [0, 0, 0, 0]; 251 | let mut c: u8; /* 4bitの圧縮データ */ 252 | let mut data: u8 = 0; 253 | for block in 0..number_of_block { 254 | let offset: usize = samples_per_block as usize * block as usize; 255 | 256 | for n in 0..samples_per_block { 257 | x = (pcm.s[offset + n as usize] + 1.0) / 2.0 * 65536.0; 258 | if x > 65535.0 { 259 | x = 65535.0; /* クリッピング */ 260 | } else if x < 0.0 { 261 | x = 0.0; /* クリッピング */ 262 | } 263 | s = ((x + 0.5) as i32 - 32768) as i16; /* 四捨五入とオフセットの調節 */ 264 | if block == 0 && n == 0 { 265 | index = 0; /* 最初のブロックにおけるindexの初期値を0にする */ 266 | } 267 | 268 | if n == 0 { 269 | header[0] = (s & 0x00FF) as u8; /* sの下位バイト */ 270 | header[1] = ((s >> 8) & 0x00FF) as u8; /* sの上位バイト */ 271 | header[2] = index as u8; /* インデックス */ 272 | header[3] = 0; 273 | write_u8x4(&mut fp, header); /* ヘッダの書き出し */ 274 | 275 | sp = s as i32; /* spの初期値をsにする */ 276 | } else { 277 | d = s as i32 - sp as i32; 278 | if d < 0 { 279 | c = 0x8; 280 | d = -d; 281 | } else { 282 | c = 0x0; 283 | } 284 | step_size = step_size_table[index as usize]; 285 | 286 | /* 圧縮 */ 287 | if d >= step_size { 288 | c |= 0x4; 289 | d -= step_size; 290 | } 291 | if d >= (step_size >> 1) { 292 | c |= 0x2; 293 | d -= step_size >> 1; 294 | } 295 | if d >= (step_size >> 2) { 296 | c |= 0x1; 297 | } 298 | 299 | /* 伸張 */ 300 | dp = step_size >> 3; 301 | if (c & 0x1) == 0x1 { 302 | dp += step_size >> 2; 303 | } 304 | if (c & 0x2) == 0x2 { 305 | dp += step_size >> 1; 306 | } 307 | if (c & 0x4) == 0x4 { 308 | dp += step_size; 309 | } 310 | 311 | if (c & 0x8) == 0x8 { 312 | sp -= dp; 313 | } else { 314 | sp += dp; 315 | } 316 | 317 | if sp > 32767 { 318 | sp = 32767; 319 | } else if sp < -32768 { 320 | sp = -32768; 321 | } 322 | 323 | index += index_table[c as usize]; 324 | 325 | if index < 0 { 326 | index = 0; 327 | } else if index > 88 { 328 | index = 88; 329 | } 330 | 331 | if (n % 2) == 1 { 332 | data = c & 0xF; /* dataの下位4bit */ 333 | } else { 334 | data |= (c & 0xF) << 4; /* dataの上位4bit */ 335 | 336 | fp.write_u8(data).unwrap() 337 | } 338 | } 339 | } 340 | } 341 | } 342 | 343 | #[allow(non_snake_case)] 344 | pub fn wave_write_8bit_mono_safer3(path: &str, pcm: &MonoPcm) { 345 | let mut fp = wave_write_header::(path, pcm); 346 | for n in 0..pcm.get_length() { 347 | fp.write_u8(WaveData::convert_from_float(pcm.s[n])).unwrap(); /* 音データの書き出し */ 348 | } 349 | if (pcm.length % 2) == 1 { 350 | /* 音データの長さが奇数のとき */ 351 | 352 | fp.write_u8(0).unwrap(); /* 0パディング */ 353 | } 354 | } 355 | 356 | #[allow(non_snake_case)] 357 | pub fn wave_write_8bit_stereo_safer3(path: &str, pcm: &StereoPcm) { 358 | let mut fp = wave_write_header::(path, pcm); 359 | for n in 0..pcm.length { 360 | fp.write_u8(WaveData::convert_from_float(pcm.s_l[n])) 361 | .unwrap(); /* 音データ(Lチャンネル)の書き出し */ 362 | fp.write_u8(WaveData::convert_from_float(pcm.s_r[n])) 363 | .unwrap(); /* 音データ(Rチャンネル)の書き出し */ 364 | } 365 | } 366 | 367 | #[allow(non_snake_case)] 368 | pub fn wave_read_PCMU_mono_safer3(path: &str) -> MonoPcm { 369 | let (mut fp, pcm_fs, _, data_chunk_size) = read::read_header2(path, true); 370 | let pcm_length = data_chunk_size as usize; 371 | let mut pcm_s = vec![0.0; pcm_length]; 372 | 373 | for n in 0..pcm_length { 374 | let data = PCMU(fp.read_u8().unwrap()); 375 | pcm_s[n] = data.convert_to_float(); /* 音データを-1以上1未満の範囲に正規化する */ 376 | } 377 | 378 | return MonoPcm { 379 | s: pcm_s, 380 | fs: pcm_fs as usize, 381 | bits: 16 as i32, 382 | length: pcm_length as usize, 383 | }; 384 | } 385 | 386 | #[allow(non_snake_case)] 387 | pub fn wave_write_PCMU_mono_safer3(path: &str, pcm: &MonoPcm) { 388 | let mut fp = wave_write_header::(path, pcm); 389 | 390 | for n in 0..pcm.get_length() { 391 | let PCMU(dat) = WaveData::convert_from_float(pcm.s[n]); 392 | fp.write_u8(dat).unwrap(); /* 音データの書き出し */ 393 | } 394 | if (pcm.length % 2) == 1 { 395 | /* 音データの長さが奇数のとき */ 396 | 397 | fp.write_u8(0).unwrap(); /* 0パディング */ 398 | } 399 | } 400 | 401 | #[allow(non_snake_case)] 402 | pub fn wave_read_PCMA_mono_safer3(path: &str) -> MonoPcm { 403 | let (mut fp, pcm_fs, _, data_chunk_size) = read::read_header2(path, true); 404 | let pcm_length = data_chunk_size as usize; 405 | let mut pcm_s = vec![0.0; pcm_length]; 406 | 407 | for n in 0..pcm_length { 408 | let data = PCMA(fp.read_u8().unwrap()); 409 | pcm_s[n] = data.convert_to_float(); /* 音データを-1以上1未満の範囲に正規化する */ 410 | } 411 | 412 | return MonoPcm { 413 | s: pcm_s, 414 | fs: pcm_fs as usize, 415 | bits: 16 as i32, 416 | length: pcm_length as usize, 417 | }; 418 | } 419 | 420 | struct PCMA(u8); 421 | struct PCMU(u8); 422 | 423 | #[allow(non_snake_case)] 424 | pub fn wave_write_PCMA_mono_safer3(path: &str, pcm: &MonoPcm) { 425 | let mut fp = wave_write_header::(path, pcm); 426 | 427 | for n in 0..pcm.get_length() { 428 | let PCMA(dat) = WaveData::convert_from_float(pcm.s[n]); 429 | fp.write_u8(dat).unwrap(); /* 音データの書き出し */ 430 | } 431 | if (pcm.length % 2) == 1 { 432 | /* 音データの長さが奇数のとき */ 433 | 434 | fp.write_u8(0).unwrap(); /* 0パディング */ 435 | } 436 | } 437 | 438 | #[allow(non_snake_case)] 439 | pub fn wave_write_16bit_stereo_safer3(path: &str, pcm: &StereoPcm) { 440 | let mut fp = wave_write_header::(path, pcm); 441 | for n in 0..pcm.length { 442 | fp.write_i16::(WaveData::convert_from_float(pcm.s_l[n])) 443 | .unwrap(); /* 音データ(Lチャンネル)の書き出し */ 444 | fp.write_i16::(WaveData::convert_from_float(pcm.s_r[n])) 445 | .unwrap(); /* 音データ(Rチャンネル)の書き出し */ 446 | } 447 | } 448 | 449 | pub fn wave_write_16bit_mono_safer3(path: &str, pcm: &MonoPcm) { 450 | let mut fp = wave_write_header::(path, pcm); 451 | for n in 0..pcm.get_length() { 452 | fp.write_i16::(WaveData::convert_from_float(pcm.s[n])) 453 | .unwrap(); /* 音データの書き出し */ 454 | } 455 | } 456 | 457 | impl WaveData for PCMU { 458 | fn convert_to_float(&self) -> f64 { 459 | let s: i16; /* 16bitの音データ */ 460 | let magnitude: i32; 461 | 462 | let PCMU(mut c) = self; /* 8bitの圧縮データ */ 463 | c = !c; 464 | 465 | let sign: u8 = c & 0x80; 466 | let exponent: u8 = (c >> 4) & 0x07; 467 | let mantissa: u8 = c & 0x0F; 468 | 469 | magnitude = ((((mantissa as i32) << 3) + 0x84) << exponent) - 0x84; 470 | 471 | if sign == 0x80 { 472 | s = -(magnitude as i16); 473 | } else { 474 | s = magnitude as i16; 475 | } 476 | 477 | s as f64 / 32768.0 /* 音データを-1以上1未満の範囲に正規化する */ 478 | } 479 | const MYSTERIOUS: i32 = 50; 480 | const BYTE_NUM: i32 = 1; 481 | const CHUNK_SIZE: i32 = 18; 482 | const WAVE_FORMAT_TYPE: i16 = 7; 483 | fn convert_from_float(d: f64) -> Self { 484 | let mut x: f64; 485 | let s: i16; /* 16bitの音データ */ 486 | let c: u8; /* 8bitの圧縮データ */ 487 | let sign: u8; 488 | let mut exponent: u8; 489 | let mantissa: u8; 490 | let mut magnitude: i32; 491 | let level: [i16; 8] = [ 492 | 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF 493 | ]; 494 | 495 | x = (d + 1.0) / 2.0 * 65536.0; 496 | 497 | if x > 65535.0 { 498 | x = 65535.0; /* クリッピング */ 499 | } else if x < 0.0 { 500 | x = 0.0; /* クリッピング */ 501 | } 502 | 503 | s = ((x + 0.5) as i32 - 32768) as i16; /* 四捨五入とオフセットの調節 */ 504 | 505 | if s < 0 { 506 | magnitude = -s as i32; 507 | sign = 0x80; 508 | } else { 509 | magnitude = s as i32; 510 | sign = 0x00; 511 | } 512 | 513 | magnitude += 0x84; 514 | if magnitude > 32767 { 515 | magnitude = 0x7FFF; 516 | } 517 | exponent = 0; 518 | while exponent < 8 { 519 | if magnitude <= level[exponent as usize] as i32 { 520 | break; 521 | } 522 | exponent += 1; 523 | } 524 | 525 | mantissa = ((magnitude >> (exponent + 3)) & 0x0F) as u8; 526 | 527 | c = !(sign | (exponent << 4) | mantissa); 528 | 529 | PCMU(c) /* 圧縮データの書き出し */ 530 | } 531 | } 532 | 533 | pub trait WaveData { 534 | fn convert_from_float(d: f64) -> Self; 535 | fn convert_to_float(&self) -> f64; 536 | const BYTE_NUM: i32; 537 | const MYSTERIOUS: i32; 538 | const CHUNK_SIZE: i32; 539 | const WAVE_FORMAT_TYPE: i16; 540 | } 541 | 542 | impl WaveData for u8 { 543 | fn convert_to_float(&self) -> f64 { 544 | (*self as f64 - 128.0) / 128.0 /* 音データを-1以上1未満の範囲に正規化する */ 545 | } 546 | fn convert_from_float(d: f64) -> u8 { 547 | let mut s = (d + 1.0) / 2.0 * 256.0; 548 | 549 | if s > 255.0 { 550 | s = 255.0; /* クリッピング */ 551 | } else if s < 0.0 { 552 | s = 0.0; /* クリッピング */ 553 | } 554 | 555 | ((s + 0.5) as i32) as u8 /* 四捨五入 */ 556 | } 557 | const BYTE_NUM: i32 = 1; 558 | const MYSTERIOUS: i32 = 36; 559 | const CHUNK_SIZE: i32 = 16; 560 | const WAVE_FORMAT_TYPE: i16 = 1; 561 | } 562 | 563 | impl WaveData for i16 { 564 | fn convert_to_float(&self) -> f64 { 565 | (*self as f64) / 32768.0 566 | } 567 | fn convert_from_float(d: f64) -> i16 { 568 | let mut s = (d + 1.0) / 2.0 * 65536.0; 569 | 570 | if s > 65535.0 { 571 | s = 65535.0; /* クリッピング */ 572 | } else if s < 0.0 { 573 | s = 0.0; /* クリッピング */ 574 | } 575 | 576 | ((s + 0.5) as i32 - 32768) as i16 /* 四捨五入とオフセットの調節 */ 577 | } 578 | const BYTE_NUM: i32 = 2; 579 | const MYSTERIOUS: i32 = 36; 580 | const CHUNK_SIZE: i32 = 16; 581 | const WAVE_FORMAT_TYPE: i16 = 1; 582 | } 583 | 584 | impl WaveData for PCMA { 585 | fn convert_to_float(&self) -> f64 { 586 | let PCMA(mut c) = *self; /* 8bitの圧縮データ */ 587 | c ^= 0xD5; 588 | let sign: u8 = c & 0x80; 589 | let exponent: u8 = (c >> 4) & 0x07; 590 | let mantissa: u8 = c & 0x0F; 591 | let magnitude: i32 = if exponent == 0 { 592 | ((mantissa as i32) << 4) + 0x0008 593 | } else { 594 | (((mantissa as i32) << 4) + 0x0108) << (exponent - 1) 595 | }; 596 | 597 | /* 16bitの音データ */ 598 | let s: i16 = if sign == 0x80 { 599 | -(magnitude as i16) 600 | } else { 601 | magnitude as i16 602 | }; 603 | 604 | s as f64 / 32768.0 /* 音データを-1以上1未満の範囲に正規化する */ 605 | } 606 | const MYSTERIOUS: i32 = 50; 607 | const BYTE_NUM: i32 = 1; 608 | const CHUNK_SIZE: i32 = 18; 609 | const WAVE_FORMAT_TYPE: i16 = 6; 610 | fn convert_from_float(d: f64) -> PCMA { 611 | let mut x: f64 = (d + 1.0) / 2.0 * 65536.0; 612 | let level: [i16; 8] = [ 613 | 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF 614 | ]; 615 | 616 | if x > 65535.0 { 617 | x = 65535.0; /* クリッピング */ 618 | } else if x < 0.0 { 619 | x = 0.0; /* クリッピング */ 620 | } 621 | 622 | let s = ((x + 0.5) as i32 - 32768) as i16; /* 四捨五入とオフセットの調節 */ 623 | 624 | let (mut magnitude, sign): (i32, u8) = if s < 0 { 625 | (-s as i32, 0x80) 626 | } else { 627 | (s as i32, 0x00) 628 | }; 629 | 630 | if magnitude > 32767 { 631 | magnitude = 0x7FFF; 632 | } 633 | 634 | let mut exponent = 0 as u8; 635 | while exponent < 8 { 636 | if magnitude <= level[exponent as usize] as i32 { 637 | break; 638 | } 639 | exponent += 1; 640 | } 641 | 642 | let mantissa: u8 = if exponent == 0 { 643 | (magnitude >> 4) & 0x0F 644 | } else { 645 | (magnitude >> (exponent + 3)) & 0x0F 646 | } as u8; 647 | 648 | PCMA((sign | (exponent << 4) | mantissa) ^ 0xD5) 649 | } 650 | } 651 | -------------------------------------------------------------------------------- /sound_programming/wave_utils/src/wave/read.rs: -------------------------------------------------------------------------------- 1 | extern crate byteorder; 2 | use self::byteorder::{LittleEndian, ReadBytesExt}; 3 | use std::fs::File; 4 | 5 | pub fn read_i8x4(mut fp: T) -> [i8; 4] 6 | where 7 | T: byteorder::ReadBytesExt, 8 | { 9 | let mut arr = [0; 4]; 10 | for item in arr.iter_mut() { 11 | *item = fp.read_i8().unwrap(); 12 | } 13 | return arr; 14 | } 15 | 16 | pub fn read_u8x4(mut fp: T) -> [u8; 4] 17 | where 18 | T: byteorder::ReadBytesExt, 19 | { 20 | let mut arr = [0; 4]; 21 | for item in arr.iter_mut() { 22 | *item = fp.read_u8().unwrap(); 23 | } 24 | return arr; 25 | } 26 | 27 | #[allow(non_snake_case)] 28 | pub fn read_header(file_name: &str) -> (File, i32, i16, i32) { 29 | read_header2(file_name, false) 30 | } 31 | 32 | #[allow(non_snake_case)] 33 | pub fn read_partial_header(file_name: &str) -> (File, i32, i16, i16) { 34 | let mut fp = File::open(file_name).expect("file not found"); 35 | 36 | let _riff_chunk_ID = read_i8x4(&mut fp); 37 | let _riff_chunk_size = fp.read_i32::().unwrap(); 38 | let _file_format_type = read_i8x4(&mut fp); 39 | let _fmt_chunk_ID = read_i8x4(&mut fp); 40 | let _fmt_chunk_size = fp.read_i32::().unwrap(); 41 | let _wave_format_type = fp.read_i16::().unwrap(); 42 | let _channel = fp.read_i16::().unwrap(); 43 | let samples_per_sec = fp.read_i32::().unwrap(); 44 | let _bytes_per_sec = fp.read_i32::().unwrap(); 45 | let block_size = fp.read_i16::().unwrap(); 46 | let bits_per_sample = fp.read_i16::().unwrap(); 47 | (fp, samples_per_sec, block_size, bits_per_sample) 48 | } 49 | 50 | #[allow(non_snake_case)] 51 | pub fn read_header2(file_name: &str, b: bool) -> (File, i32, i16, i32) { 52 | let (mut fp, samples_per_sec, _block_size, bits_per_sample) = read_partial_header(file_name); 53 | 54 | if b { 55 | { 56 | let extra_size = fp.read_i16::().unwrap(); 57 | assert_eq!(extra_size, 0); 58 | } 59 | { 60 | let fact_chunk_ID = read_i8x4(&mut fp); 61 | assert_eq!(fact_chunk_ID, ['f' as i8, 'a' as i8, 'c' as i8, 't' as i8]); 62 | } 63 | let _fact_chunk_size = fp.read_i32::().unwrap(); 64 | let _sample_length = fp.read_i32::().unwrap(); 65 | } 66 | { 67 | let data_chunk_ID = read_i8x4(&mut fp); 68 | assert_eq!(data_chunk_ID, ['d' as i8, 'a' as i8, 't' as i8, 'a' as i8]); 69 | } 70 | let data_chunk_size = fp.read_i32::().unwrap(); 71 | 72 | return (fp, samples_per_sec, bits_per_sample, data_chunk_size); 73 | } 74 | -------------------------------------------------------------------------------- /sound_programming/wave_utils/src/wave/write.rs: -------------------------------------------------------------------------------- 1 | extern crate byteorder; 2 | use self::byteorder::{LittleEndian, WriteBytesExt}; 3 | use MonoPcm; 4 | use StereoPcm; 5 | use std::fs::File; 6 | use wave::WaveData; 7 | 8 | pub fn write_i8x4(mut fp: T, arr: [i8; 4]) 9 | where 10 | T: byteorder::WriteBytesExt, 11 | { 12 | for item in arr.iter() { 13 | fp.write_i8(*item).unwrap(); 14 | } 15 | } 16 | 17 | pub fn write_u8x4(mut fp: T, arr: [u8; 4]) 18 | where 19 | T: byteorder::WriteBytesExt, 20 | { 21 | for item in arr.iter() { 22 | fp.write_u8(*item).unwrap(); 23 | } 24 | } 25 | 26 | #[allow(non_snake_case)] 27 | pub fn wave_write_header_partial( 28 | path: &str, 29 | umysterious: i32, 30 | bar: i32, 31 | uchunksize: i32, 32 | wave_format_type: i16, 33 | tchannel: i32, 34 | fs: usize, 35 | bytes_per_sec: i32, 36 | block_size: i16, 37 | bits_per_sample: i16, 38 | ) -> File { 39 | let mut fp = File::create(path).expect("file cannot be created"); 40 | let riff_chunk_ID: [i8; 4] = ['R' as i8, 'I' as i8, 'F' as i8, 'F' as i8]; 41 | let riff_chunk_size: i32 = umysterious + bar; 42 | let file_format_type: [i8; 4] = ['W' as i8, 'A' as i8, 'V' as i8, 'E' as i8]; 43 | let fmt_chunk_ID: [i8; 4] = ['f' as i8, 'm' as i8, 't' as i8, ' ' as i8]; 44 | let fmt_chunk_size: i32 = uchunksize; 45 | let wave_format_type: i16 = wave_format_type; 46 | let channel: i16 = tchannel as i16; 47 | let samples_per_sec: i32 = fs as i32; /* 標本化周波数 */ 48 | 49 | write_i8x4(&mut fp, riff_chunk_ID); 50 | fp.write_i32::(riff_chunk_size).unwrap(); 51 | write_i8x4(&mut fp, file_format_type); 52 | write_i8x4(&mut fp, fmt_chunk_ID); 53 | fp.write_i32::(fmt_chunk_size).unwrap(); 54 | fp.write_i16::(wave_format_type).unwrap(); 55 | fp.write_i16::(channel).unwrap(); 56 | fp.write_i32::(samples_per_sec).unwrap(); 57 | fp.write_i32::(bytes_per_sec).unwrap(); 58 | fp.write_i16::(block_size).unwrap(); 59 | fp.write_i16::(bits_per_sample).unwrap(); 60 | 61 | fp 62 | } 63 | 64 | #[allow(non_snake_case)] 65 | pub fn wave_write_header(path: &str, pcm: &T) -> File 66 | where 67 | T: Pcm, 68 | U: WaveData, 69 | { 70 | let channel_: i32 = T::CHANNEL; 71 | let bits = U::BYTE_NUM * 8; 72 | 73 | let bits_per_sample: i16 = bits as i16; /* 量子化精度 */ 74 | 75 | let mut fp = wave_write_header_partial( 76 | path, 77 | U::MYSTERIOUS, 78 | U::BYTE_NUM * channel_ * pcm.get_length() as i32, 79 | U::CHUNK_SIZE, 80 | U::WAVE_FORMAT_TYPE, 81 | T::CHANNEL, 82 | pcm.get_fs(), 83 | pcm.get_fs() as i32 * bits / 8 * channel_, 84 | (bits / 8) as i16 * channel_ as i16, 85 | bits_per_sample, 86 | ); 87 | 88 | if U::CHUNK_SIZE == 18 { 89 | let extra_size: i16 = 0; 90 | let fact_chunk_ID: [i8; 4] = ['f' as i8, 'a' as i8, 'c' as i8, 't' as i8]; 91 | let fact_chunk_size: i32 = 4; 92 | let sample_length: i32 = pcm.get_length() as i32; 93 | 94 | fp.write_i16::(extra_size).unwrap(); 95 | write_i8x4(&mut fp, fact_chunk_ID); 96 | fp.write_i32::(fact_chunk_size).unwrap(); 97 | fp.write_i32::(sample_length).unwrap(); 98 | } 99 | let data_chunk_ID: [i8; 4] = ['d' as i8, 'a' as i8, 't' as i8, 'a' as i8]; 100 | let data_chunk_size: i32 = pcm.get_length() as i32 * U::BYTE_NUM * channel_; 101 | write_i8x4(&mut fp, data_chunk_ID); 102 | fp.write_i32::(data_chunk_size).unwrap(); 103 | return fp; 104 | } 105 | 106 | pub trait Pcm { 107 | fn get_fs(&self) -> usize; 108 | fn get_length(&self) -> usize; 109 | const CHANNEL: i32; 110 | } 111 | 112 | impl Pcm for MonoPcm { 113 | fn get_fs(&self) -> usize { 114 | self.fs 115 | } 116 | fn get_length(&self) -> usize { 117 | self.length 118 | } 119 | const CHANNEL: i32 = 1; 120 | } 121 | 122 | impl Pcm for StereoPcm { 123 | fn get_fs(&self) -> usize { 124 | self.fs 125 | } 126 | fn get_length(&self) -> usize { 127 | self.length 128 | } 129 | const CHANNEL: i32 = 2; 130 | } 131 | -------------------------------------------------------------------------------- /sound_programming/white_noise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hsjoihs/sound_programming_rust/a7ccb7571ae037b86b298482624318d3b63b1a2b/sound_programming/white_noise.wav --------------------------------------------------------------------------------