Class: Pitch
- Inherits:
-
Object
- Object
- Pitch
- Defined in:
- lib/pitch.rb
Constant Summary collapse
- SEMITONE_NAMES =
%w[C C# D D# E F F# G G# A A# B]
- NUM_SEMITONES =
SEMITONE_NAMES.count
Instance Attribute Summary collapse
-
#octave ⇒ Object
Returns the value of attribute octave.
-
#semitone ⇒ Object
Returns the value of attribute semitone.
Class Method Summary collapse
- .new_from_midi(arg) ⇒ Object
- .new_from_midi_name(name) ⇒ Object
- .new_from_midi_num(num) ⇒ Object
- .new_from_spn(spn) ⇒ Object
- .parse_name(name) ⇒ Object
- .read_from_file(file) ⇒ Object
- .run_command(*args) ⇒ Object
Instance Method Summary collapse
- #+(n) ⇒ Object
- #-(n) ⇒ Object
- #==(other) ⇒ Object
-
#initialize(semitone, octave) ⇒ Pitch
constructor
A new instance of Pitch.
- #to_midi_name ⇒ Object
- #to_midi_num ⇒ Object
- #to_s(offset: 0) ⇒ Object
- #to_spn ⇒ Object
- #write_to_file(file, duration: 5, rate: 48000, depth: 24) ⇒ Object
Constructor Details
#initialize(semitone, octave) ⇒ Pitch
Returns a new instance of Pitch.
63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/pitch.rb', line 63 def initialize(semitone, octave) @semitone = case semitone when Numeric semitone when String SEMITONE_NAMES.index(semitone) else raise ArgumentError end @octave = octave end |
Instance Attribute Details
#octave ⇒ Object
Returns the value of attribute octave.
6 7 8 |
# File 'lib/pitch.rb', line 6 def octave @octave end |
#semitone ⇒ Object
Returns the value of attribute semitone.
5 6 7 |
# File 'lib/pitch.rb', line 5 def semitone @semitone end |
Class Method Details
.new_from_midi(arg) ⇒ Object
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/pitch.rb', line 30 def self.new_from_midi(arg) case arg when Numeric new_from_midi_num(arg) when String new_from_midi_name(arg) else raise ArgumentError end end |
.new_from_midi_name(name) ⇒ Object
46 47 48 49 |
# File 'lib/pitch.rb', line 46 def self.new_from_midi_name(name) semitone, octave = parse_name(name) new(semitone, octave + 1) end |
.new_from_midi_num(num) ⇒ Object
41 42 43 44 |
# File 'lib/pitch.rb', line 41 def self.new_from_midi_num(num) semitone, octave = SEMITONE_NAMES[num % NUM_SEMITONES], (num / NUM_SEMITONES) new(semitone, octave - 1) end |
.new_from_spn(spn) ⇒ Object
51 52 53 54 |
# File 'lib/pitch.rb', line 51 def self.new_from_spn(spn) semitone, octave = parse_name(spn) new(semitone, octave) end |
.parse_name(name) ⇒ Object
56 57 58 59 60 61 |
# File 'lib/pitch.rb', line 56 def self.parse_name(name) semitone_name, octave = name.match(/^(.*?)(-?\d+)$/).captures semitone = SEMITONE_NAMES.index(semitone_name) octave = octave.to_i [semitone, octave] end |
.read_from_file(file) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/pitch.rb', line 11 def self.read_from_file(file) out, _ = run_command( 'aubiopitch', '--samplerate', 48000, # doesn't work with higher sample rates? '--input', file, '--pitch-unit', 'midi', ) values = out.split(/\n/).map { |line| line.split(/\s+/).last.to_f }.reject(&:zero?) raise "Couldn't detect pitches" if values.empty? value = (values.sum / values.count).round new_from_midi_num(value) end |
.run_command(*args) ⇒ Object
24 25 26 27 28 |
# File 'lib/pitch.rb', line 24 def self.run_command(*args) TTY::Command.new(printer: :quiet).run( *args.flatten.compact.map(&:to_s), only_output_on_error: true) end |
Instance Method Details
#+(n) ⇒ Object
100 101 102 |
# File 'lib/pitch.rb', line 100 def +(n) self.class.new_from_midi_num(to_midi_num + n) end |
#-(n) ⇒ Object
104 105 106 |
# File 'lib/pitch.rb', line 104 def -(n) self + (-n) end |
#==(other) ⇒ Object
75 76 77 78 79 |
# File 'lib/pitch.rb', line 75 def ==(other) other && @octave == other.octave && @semitone == other.semitone end |
#to_midi_name ⇒ Object
81 82 83 |
# File 'lib/pitch.rb', line 81 def to_midi_name to_s(offset: -1) end |
#to_midi_num ⇒ Object
85 86 87 |
# File 'lib/pitch.rb', line 85 def to_midi_num ((@octave + 1) * NUM_SEMITONES) + @semitone end |
#to_s(offset: 0) ⇒ Object
93 94 95 96 97 98 |
# File 'lib/pitch.rb', line 93 def to_s(offset: 0) '%s%d' % [ SEMITONE_NAMES[@semitone], @octave + offset, ] end |
#to_spn ⇒ Object
89 90 91 |
# File 'lib/pitch.rb', line 89 def to_spn to_s end |
#write_to_file(file, duration: 5, rate: 48000, depth: 24) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/pitch.rb', line 108 def write_to_file(file, duration: 5, rate: 48000, depth: 24) self.class.run_command( 'sox', '--null', '--rate', rate, '--bits', depth, file, 'synth', duration, 'pluck', to_spn, ) file end |