Skip to content

Commit b43abe5

Browse files
committed
BREAKING CHANGE: Change behaviour of invert_chord
This commit does two things: a) Guards against an error calling rings with out of range index ranges b) Makes a breaking change to the behaviour of negative inversions Prior to this, the implementation of `invert_chord`, when given an argument of say -1 for the no. of inversions would do this: ``` puts invert_chord([60, 64, 67], -1) # => [64,67,48] puts invert_chord([60, 64, 67], -2) # => [67,48,52] ``` Musically speaking, it makes more sense to move the top voice down an octave first, so that the chord is voiced as closely together as possible i.e. `[:g3, :c4, :e4]` - this voicing is skipped over by the previous implementation. See added tests for more details.
1 parent 61a8dd4 commit b43abe5

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

app/server/sonicpi/lib/sonicpi/mods/sound.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2723,9 +2723,9 @@ def invert_chord(notes, shift)
27232723
raise "Inversion shift value must be a number, got #{shift.inspect}" unless shift.is_a?(Numeric)
27242724
raise "Notes must be a list of notes, got #{notes.inspect}" unless (notes.is_a?(SonicPi::Core::RingVector) || notes.is_a?(Array))
27252725
if(shift > 0)
2726-
invert_chord(notes[1..-1] + [notes[0]+12], shift-1)
2726+
invert_chord(notes.to_a[1..-1] + [notes.to_a[0]+12], shift-1)
27272727
elsif(shift < 0)
2728-
invert_chord(notes[1..-1] + [notes[0]-12], shift+1)
2728+
invert_chord((notes.to_a[0..-2] + [notes.to_a[-1]-12]).sort, shift+1)
27292729
else
27302730
notes.ring
27312731
end
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#--
2+
# This file is part of Sonic Pi: http://sonic-pi.net
3+
# Full project source: https://github.com/samaaron/sonic-pi
4+
# License: https://github.com/samaaron/sonic-pi/blob/master/LICENSE.md
5+
#
6+
# Copyright 2013, 2014, 2015 by Sam Aaron (http://sam.aaron.name).
7+
# All rights reserved.
8+
#
9+
# Permission is granted for use, copying, modification, and
10+
# distribution of modified versions of this work as long as this
11+
# notice is included.
12+
#++
13+
14+
require 'test/unit'
15+
require_relative "../../core"
16+
require_relative "../lib/sonicpi/chord"
17+
require_relative "../lib/sonicpi/mods/sound"
18+
19+
module SonicPi
20+
module Mods
21+
module Sound
22+
module_function :invert_chord
23+
module_function :chord
24+
end
25+
end
26+
class InvertChordTester < Test::Unit::TestCase
27+
28+
def test_inversion_of_basic_major
29+
assert_equal(Mods::Sound.invert_chord(Chord.new(:C4, :major), 0), [60, 64, 67])
30+
assert_equal(Mods::Sound.invert_chord(Chord.new(:C4, :major), 1), [64, 67, 72])
31+
assert_equal(Mods::Sound.invert_chord(Chord.new(:C4, :major), 2), [67, 72, 76])
32+
33+
# what should happen the other way...
34+
assert_equal(Mods::Sound.invert_chord(Chord.new(:C4, :major), -1).sort, [55, 60, 64])
35+
assert_equal(Mods::Sound.invert_chord(Chord.new(:C4, :major), -2).sort, [52, 55, 60])
36+
assert_equal(Mods::Sound.invert_chord(Chord.new(:C4, :major), -3).sort, [48, 52, 55])
37+
38+
# edge case
39+
assert_equal(Mods::Sound.invert_chord(Mods::Sound.chord(:C4, "1"), 1), [72])
40+
assert_equal(Mods::Sound.invert_chord(Mods::Sound.chord(:C4, "1"), -1), [48])
41+
end
42+
43+
end
44+
end

0 commit comments

Comments
 (0)