ソースを参照

Merge branch 'master' of schdbr.de:woelper/sampler

Johann Woelper 4 年 前
コミット
6a655b515d
4 ファイル変更98 行追加44 行削除
  1. 27 2
      Readme.md
  2. 6 6
      sampler.ini
  3. 25 9
      src/base.rs
  4. 40 27
      src/main.rs

+ 27 - 2
Readme.md

@@ -1,3 +1,28 @@
-A simple sampler written in rust
+# A simple sampler.
 
-All samples are CC0-licensed, so you can use them in your projects.
+
+A toy project for fooling around with rust, imgui and rodio.
+
+The concept is centered around `Sound`s, `Pattern`s and a `Timeline`.
+You can select and modify individual sounds and arrange them on a pattern. Afterwards, arrange patterns on a timeline to form a song (planned)
+
+What you can do now:
+- Combine any number of sounds into a pattern
+- Sounds can be adjusted:
+    - speed
+    - volume
+    - trim (planned)
+    - reverse (planned)
+    - roll (planned)
+- Patterns can be adjusted:
+    - repeat
+    - BPM
+    - length
+    - rows
+- Save your patterns to disk
+- Load patterns from disk
+- Comes with CC0-licensed samples that are ready to use
+- Add your own sounds into the media folder
+
+What you can not do:
+- Export your song 

+ 6 - 6
sampler.ini

@@ -9,7 +9,7 @@ Size=300,100
 Collapsed=0
 
 [Window][sources]
-Pos=495,-20
+Pos=861,106
 Size=361,711
 Collapsed=0
 
@@ -29,23 +29,23 @@ Size=328,168
 Collapsed=0
 
 [Window][sound]
-Pos=6,272
+Pos=71,153
 Size=354,269
 Collapsed=0
 
 [Window][tracks]
-Pos=677,214
+Pos=983,-71
 Size=300,160
 Collapsed=0
 
 [Window][pattern]
-Pos=76,420
-Size=684,294
+Pos=38,658
+Size=826,309
 Collapsed=0
 
 [Window][patterns]
 Pos=400,140
-Size=324,183
+Size=414,352
 Collapsed=0
 
 [Window][settings]

+ 25 - 9
src/base.rs

@@ -28,8 +28,7 @@ pub struct Sound {
     pub roll: i32,
     pub rollrate: i32,
     pub trim: f32,
-    pub active: bool,
-    pub speed: f32,
+      pub speed: f32,
     #[serde(default)]
     pub reverse: bool
 }
@@ -41,6 +40,8 @@ impl AsRef<[u8]> for Sound {
 }
 
 impl Sound {
+
+    /// Produce a new Sound struct from a filename
     pub fn new(filename: &PathBuf) -> std::io::Result<Sound> {
         let mut buf = Vec::new();
         let sanitized_name = PathBuf::from(filename.to_string_lossy().replace("\\", "/"));
@@ -60,11 +61,23 @@ impl Sound {
         })
     }
 
-    // pub fn reload(mut self) {
-    //     if let Ok(s) = Sound::new(&self.location.to_string_lossy()) {
-    //         self.data = s.data;
-    //     }
-    // }
+    pub fn duration(&self) -> Option<Duration> {
+
+        // let file = File::open(&self.location).unwrap();
+        // let source = rodio::Decoder::new(BufReader::new(file)).unwrap();
+        // let d = source.total_duration();
+        
+        match Decoder::new(self.cursor()) {
+            Ok(ok_decoder) => {
+                ok_decoder.total_duration()
+            }
+            Err(e) => {
+                dbg!(e);
+                None
+            }
+        }
+
+    }
 
     pub fn updated_from_source(&self) -> Result<Sound, std::io::Error>{
         Sound::new(&self.location)
@@ -223,6 +236,11 @@ impl Pattern {
 
     }
 
+    pub fn duration(&self) -> u64 {
+        ((60.0 / self.bpm as f32)*1000.0) as u64 * self.xsize as u64
+
+    }
+
     /// Deserialize a pattern from a file.
     pub fn load(file: &Path) -> Result<Pattern, String> {
         match File::open(file) {
@@ -258,8 +276,6 @@ impl Pattern {
         }
     }
 
-
-
     /// Guess the name from the most commpn sound in a pattern.
     pub fn name_from_row(&self, row: usize) -> String {
         let mut names: HashMap<String, usize> = HashMap::new();

+ 40 - 27
src/main.rs

@@ -63,7 +63,6 @@ fn main() {
     style.window_rounding = 1.5;
     style.anti_aliased_lines = false;
     style.anti_aliased_fill = false;
-
     
     const PURPLE: [f32; 4] = [0.07, 0.05, 0.27, 1.00];
     system.main_loop(move |_, ui| {
@@ -222,37 +221,50 @@ fn main() {
             Window::new(im_str!("sound"))
             .size([300.0, 100.0], Condition::FirstUseEver)
             .build(ui, || {
-                // let snd = &active_bar.sounds[pattern_col];
+                // check if active sounds is some
                 if let Some(s) = &mut active_sound {
                     ui.text(im_str!("name   {}", s.name));
-                    // let _ = DragFloat::new()
+
                     ui.drag_float(im_str!("volume"), &mut s.volume)
                         .min(-1.0)
                         .max(2.0)
                         .speed(0.01)
                         .build();
+
                     ui.drag_float(im_str!("speed"), &mut s.speed)
                         .min(0.0)
                         .max(2.0)
                         .speed(0.01)
-                        .build();
+                        .build();    
+                        
                     ui.drag_int(im_str!("roll"), &mut s.roll)
                         .max(32)
                         .speed(0.05)
                         .build();
-
+                        
+                    if ui.small_button(&im_str!("adjust speed to pattern")) {
+                        if let Some(sd) = s.duration() {
+                            let ad = active_pattern.duration();
+                            dbg!(&sd.as_millis());
+                            let scale = sd.as_millis() as f32 / ad as f32;
+                            dbg!(&scale);
+                            s.speed = scale;
+                        }
+                        // dbg!(&l);
+                        // let bpm = active_pattern.bpm;
+                    }
                     ui.checkbox(im_str!("reverse"), &mut s.reverse);
                 
-                    if ui.small_button(&im_str!("play")) {
-                        s.play(&dev);
-                    }
+                    if ui.small_button(&im_str!("play")) {s.play(&dev)}
                 
                 }
-                if ui.small_button(&im_str!("clear")) {
-                    active_sound = None;
-                }
+
+                if ui.small_button(&im_str!("clear")) {active_sound = None}
             });
     
+
+
+
             Window::new(im_str!("tracks"))
             .size([300.0, 100.0], Condition::FirstUseEver)
             .build(ui, || {
@@ -261,26 +273,27 @@ fn main() {
                     active_pattern.play(&dev);
                 }
             });
-    
-            Window::new(im_str!("settings"))
-            .size([300.0, 100.0], Condition::FirstUseEver)
-            .build(ui, || {
-               
-                let mut scale = 1.0;
-                if ui.drag_float(im_str!("speed"), &mut scale)
-                .min(0.0)
-                .max(3.0)
-                .speed(0.01)
-                .build() {
-                    // let s = system.imgui.style_mut();
-                    
-                    // s.scale_all_sizes(scale);
 
-                }
 
-            });
 
 
+    
+            // Window::new(im_str!("settings"))
+            // .size([300.0, 100.0], Condition::FirstUseEver)
+            // .build(ui, || {
+               
+            //     let mut scale = 1.0;
+            //     if ui.drag_float(im_str!("size"), &mut scale)
+            //     .min(0.0)
+            //     .max(3.0)
+            //     .speed(0.01)
+            //     .build() {
+            //         // let s = system.imgui.style_mut();
+            //         // s.scale_all_sizes(scale);
+            //     }
+            // });
+
+            // Discard color token
             colors.pop(&ui);
     
         });