@@ -64,6 +64,29 @@ impl Pattern {
6464 }
6565 }
6666
67+ /// Returns a pattern based on a boolean slice
68+ ///
69+ /// # Arguments
70+ ///
71+ /// * `slice` - A boolean slice holding the initial pattern
72+ ///
73+ /// # Examples
74+ ///
75+ /// ```
76+ /// use rhythms::Pattern;
77+ /// let pattern = Pattern::from_slice(&[false, false, false, true]);
78+ /// assert_eq!([false, false, false, true], pattern.as_slice());
79+ /// ```
80+ pub fn from_slice ( slice : & [ bool ] ) -> Self {
81+ Self {
82+ steps : SmallVec :: from_slice ( slice) ,
83+ length : slice. len ( ) ,
84+ cursor : 0 ,
85+ pulses : 0 ,
86+ rotation : 0 ,
87+ }
88+ }
89+
6790 /// Clears all pulses from a pattern
6891 ///
6992 /// # Examples
@@ -82,7 +105,7 @@ impl Pattern {
82105 }
83106 }
84107
85- /// Resize the current pattern
108+ /// Resize the current pattern. If length is
86109 ///
87110 /// # Arguments
88111 ///
@@ -92,46 +115,24 @@ impl Pattern {
92115 ///
93116 /// ```
94117 /// use rhythms::Pattern;
95- /// let mut pattern = Pattern::with_length(8);
118+ /// let mut pattern = Pattern::with_length(1);
119+ /// assert_eq!([false], pattern.as_slice());
96120 /// pattern.resize(4);
97121 /// assert_eq!(4, pattern.len());
122+ /// assert_eq!([false, false, false, false], pattern.as_slice());
98123 /// ```
99- pub fn resize ( & mut self , length : usize ) -> & mut Self {
100- self . steps = SmallVec :: with_capacity ( length) ;
124+ pub fn resize ( & mut self , length : usize ) {
125+ self . steps . resize ( length, false ) ;
101126 self . length = length;
102- self . pulses ( self . pulses ) ;
103- self
104127 }
105128
106- /// Returns a pattern based on a boolean slice
129+ /// Updates the current pattern with a evenly distributed number of pulses, using an
130+ /// abstraction based on Bjorklund's Euclidean algorithm.
107131 ///
108132 /// # Arguments
109133 ///
110- /// * `slice` - A boolean slice holding the initial pattern
111- ///
112- /// # Examples
113- ///
114- /// ```
115- /// use rhythms::Pattern;
116- /// let pattern = Pattern::from_slice(&[false, false, false, true]);
117- /// assert_eq!([false, false, false, true], pattern.as_slice());
118- /// ```
119- pub fn from_slice ( slice : & [ bool ] ) -> Self {
120- Self {
121- steps : SmallVec :: from_slice ( slice) ,
122- length : slice. len ( ) ,
123- cursor : 0 ,
124- pulses : 0 ,
125- rotation : 0 ,
126- }
127- }
128-
129- /// Updates the current pattern with a number of pulses, using an abstraction based on
130- /// Bjorklund's Euclidean algorithm.
131- ///
132- /// # Arguments
133- ///
134- /// * `pulses` - Total number of pulses
134+ /// * `pulses` - Total number of pulses, from `0` to the pattern length. If `pulses` exceeds
135+ /// the pattern length, the max value will be used
135136 ///
136137 /// # Examples
137138 ///
@@ -146,34 +147,29 @@ impl Pattern {
146147 /// pattern.pulses(2);
147148 /// assert_eq!([true, false, true, false], pattern.as_slice());
148149 /// ```
149- pub fn pulses ( & mut self , pulses : usize ) -> & mut Self {
150- if pulses == 0 {
151- self . clear ( ) ;
152- return self
153- }
154- let length = self . length ;
155- let pulses = if pulses > length {
156- length
150+ pub fn pulses ( & mut self , pulses : usize ) {
151+ self . pulses = if pulses > self . length {
152+ self . length
157153 } else {
158154 pulses
159155 } ;
156+
160157 self . steps . clear ( ) ;
161- self . pulses = pulses;
162158 let mut bucket: usize = 0 ;
163- for _ in 0 ..length {
164- bucket += pulses;
165- if bucket >= length {
166- bucket -= length;
159+ for _ in 0 ..self . length {
160+ bucket += self . pulses ;
161+ if bucket >= self . length {
162+ bucket -= self . length ;
167163 self . steps . push ( true ) ;
168164 } else {
169165 self . steps . push ( false ) ;
170166 }
171167 }
172- if length > 0 {
173- let offset = length / pulses - 1 ;
168+
169+ if self . length > 0 && self . pulses > 0 {
170+ let offset = self . length / self . pulses - 1 ;
174171 self . steps . rotate_right ( offset) ;
175172 }
176- self
177173 }
178174
179175 /// Rotates the current pattern
@@ -195,14 +191,13 @@ impl Pattern {
195191 /// let pattern = Pattern::new(3, 1, -1);
196192 /// assert_eq!([true, false, false], pattern.as_slice());
197193 /// ```
198- pub fn rotate ( & mut self , rotation : isize ) -> & mut Self {
194+ pub fn rotate ( & mut self , rotation : isize ) {
199195 self . rotation = rotation;
200196 if rotation. is_positive ( ) {
201197 self . steps . rotate_right ( rotation as usize ) ;
202198 } else if rotation. is_negative ( ) {
203199 self . steps . rotate_left ( rotation. abs ( ) as usize ) ;
204200 }
205- self
206201 }
207202
208203 /// Returns a boolean slice reprensenting the pattern
@@ -270,7 +265,7 @@ impl Pattern {
270265 /// ```
271266 pub fn next_looped ( & mut self ) -> bool {
272267 let step = self . steps [ self . cursor ] ;
273- if self . cursor == self . len ( ) - 1 {
268+ if self . cursor == self . last_index ( ) {
274269 self . reset ( ) ;
275270 } else {
276271 self . move_cursor ( self . cursor + 1 ) ;
@@ -312,12 +307,20 @@ impl Pattern {
312307 /// assert_eq!(Some(false), pattern.next());
313308 /// ```
314309 pub fn move_cursor ( & mut self , step : usize ) {
315- self . cursor = if step >= self . len ( ) {
316- self . len ( ) - 1
317- } else {
310+ self . cursor = if self . is_in_range ( step) {
318311 step
312+ } else {
313+ self . last_index ( )
319314 } ;
320315 }
316+
317+ fn is_in_range ( & self , step : usize ) -> bool {
318+ step < self . len ( )
319+ }
320+
321+ fn last_index ( & self ) -> usize {
322+ self . len ( ) - 1
323+ }
321324}
322325
323326/// Iterate over a pattern
@@ -332,7 +335,7 @@ impl Pattern {
332335impl Iterator for Pattern {
333336 type Item = bool ;
334337 fn next ( & mut self ) -> Option < bool > {
335- if self . cursor < self . steps . len ( ) {
338+ if self . is_in_range ( self . cursor ) {
336339 let current = self . cursor ;
337340 self . cursor += 1 ;
338341 Some ( self . steps [ current] )
@@ -427,4 +430,23 @@ mod tests {
427430 pattern. as_slice( )
428431 ) ;
429432 }
433+
434+ #[ test]
435+ fn zero_length ( ) {
436+ let pattern = Pattern :: with_length ( 0 ) ;
437+ assert_eq ! (
438+ 0 ,
439+ pattern. len( )
440+ ) ;
441+ }
442+
443+ #[ test]
444+ fn zero_pulses ( ) {
445+ let mut pattern = Pattern :: with_length ( 2 ) ;
446+ pattern. pulses ( 0 ) ;
447+ assert_eq ! (
448+ [ false , false ] ,
449+ pattern. as_slice( )
450+ ) ;
451+ }
430452}
0 commit comments