sidtool 0.0.2 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c9e6e4a8741217ee0274bdb1b6fedb7f9c170bf89466b801ad8a1857a7cc59b
4
- data.tar.gz: f2c57a83771df5654ae6c5e257eeff3ec0d94ae1d9a8db94da58f5eed2e7dee8
3
+ metadata.gz: 18bb0264bfc225b9bf717f464da9e9abc46777a93d3edd5ef985244fcc7e609d
4
+ data.tar.gz: 9a9b61aee40dadb92111f5cfc3b12e85db24f37c98f33d3981244aa8e04a1097
5
5
  SHA512:
6
- metadata.gz: bf153ba88e818359ee5df8b32de316959c9215142416a29997b204cc4545210ae33efb01e0a60155c81b1251a398cfe81736e6e1dc08392cfec0396005a3278a
7
- data.tar.gz: 8533881bb398f17eb54ef530fe3bb23f24fe8bde3214c87ec994da8c35faaa10d4e372fffc99ffab3b23add8f15ce2e268150d1cfa4736afffc159c5b32d44c0
6
+ metadata.gz: d21cd9a7aa43ae31afb6173aac169182f2cf1836fa25314dfba2633c37fc5cab74fcd9ff174000e0749e9f98db4d856860110da049308c74b769b4f7cbef3084
7
+ data.tar.gz: 56423bc991f5d6e74c56205e438967fe9ad8a12c83f0955708c3c88eddb4dc6017cb2d28f1bcfd73d8d6faa73a028eb8c944fa38261d2ea3b540303f257c1645
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.0.5
4
+ * Bumped to mos6510 version 0.1.2 which depends on a version of mini_racer that supports
5
+ Ruby 3.1.
6
+
7
+ ## 0.0.4
8
+ * Bumped to mos6510 version 0.1.1 which depends on a version of mini_racer that can compile
9
+ and install on my machine.
10
+
11
+ ## 0.0.3
12
+ * Add midi support.
13
+
3
14
  ## 0.0.2
4
15
  * Process 15000 frames (10 minutes) instead of 1500 (half a minute) by default.
5
16
  * Only release a synth once. This fixes various sound effects that would just end up with a
data/Gemfile.lock CHANGED
@@ -1,20 +1,20 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sidtool (0.0.2)
5
- mos6510 (~> 0.1.0)
4
+ sidtool (0.0.5)
5
+ mos6510 (~> 0.1.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  coderay (1.1.2)
11
11
  diff-lcs (1.3)
12
- libv8 (7.3.492.27.1-x86_64-darwin-18)
12
+ libv8-node (16.10.0.0-x86_64-darwin)
13
13
  method_source (0.9.2)
14
- mini_racer (0.2.6)
15
- libv8 (>= 6.9.411)
16
- mos6510 (0.1.0)
17
- mini_racer (~> 0.2.6)
14
+ mini_racer (0.6.2)
15
+ libv8-node (~> 16.10.0.0)
16
+ mos6510 (0.1.2)
17
+ mini_racer (~> 0.6.2)
18
18
  pry (0.12.2)
19
19
  coderay (~> 1.1.0)
20
20
  method_source (~> 0.9.0)
@@ -44,4 +44,4 @@ DEPENDENCIES
44
44
  sidtool!
45
45
 
46
46
  BUNDLED WITH
47
- 2.0.2
47
+ 2.1.4
data/README.md CHANGED
@@ -1,24 +1,36 @@
1
1
  # Sidtool
2
2
 
3
- Convert Commodore 64 SID music in the form of `.sid` files into other formats! This is still VERY
4
- much work in progress... the code is ugly and will probably create horrible results for you :-)
3
+ Convert Commodore 64 SID music in the form of `.sid` files into other formats!
5
4
 
6
- Basically, it's a massive hack made for fun and no profit.
7
-
8
- The vision, though, is to extract the actual information from `.sid` files, which are files storing
9
- music for the Commodore 64. This sounds like an easy task.
5
+ Basically, it's a massive hack made for fun and no profit. The vision, though, is to extract the
6
+ actual information from `.sid` files, which are files storing music for the Commodore 64.
10
7
 
11
8
  `.sid` files contain actual Commodore 64 machine code that writes to registers corresponding to the
12
9
  Commodore 64 sound chip, the SID (Sound Interface Device). Which means that in order to play back a
13
10
  `.sid` file like it would sound on an actual Commodore 64, you will have to simulate both the
14
11
  processor and the sound chip.
15
12
 
16
- This project does not attempt to simulate the SID chip to produce authentic sounds - lots of those
17
- players already exist - but instead has a very simple implementation that produces data that can be
18
- used to play back the songs. You know, almost as notes.
13
+ This project does not attempt to produce an authentic playback of the sounds - lots of those
14
+ players already exist - but instead lets you export a Commodore 64 song into a format that lets
15
+ you edit and experiment with the song. Want to change the instruments? Go ahead. Want to take out
16
+ parts of the song and use in other projects? You can do that. Want to just listen to your favourite
17
+ Commodore 64 song played back by a piano? Definitely do that!
18
+
19
+ ## Supported Output Formats
20
+
21
+ ### Ruby
22
+
23
+ You can get a simple Ruby file which defines a list of synths to play at certain points in time.
24
+ This can be used to play back the music in [Sonic Pi](https://sonic-pi.net) (see below), or you
25
+ can write a Ruby script to do your own post-processing.
19
26
 
20
- Currently the only output format is a Ruby file which defines a list of synths to play at certain
21
- points in time. This can be used to play back the music in [Sonic Pi](https://sonic-pi.net).
27
+ ### Midi
28
+
29
+ If you just want to listen to a `.sid` file, the easiest way is to export to midi file format and
30
+ open the file in a player such as [VLC](https://www.videolan.org/vlc/index.html). However, if you
31
+ want to further edit the result, import the file in a music editor such as GarageBand on a Mac.
32
+ Then you can use all of the tools provided by your music editor to change instruments and rearrange
33
+ the song.
22
34
 
23
35
  ## Limitations
24
36
 
@@ -46,16 +58,20 @@ Show information, like the author and number of songs in a file:
46
58
 
47
59
  $ sidtool --info <input file>
48
60
 
49
- Convert the default song from a file to a Ruby list:
61
+ Convert the default song from a `.sid` file to a midi file:
62
+
63
+ $ sidtool --out <output file> --format midi <input file>
64
+
65
+ Convert the default song from a file to a Ruby list (`--format ruby` is the default):
50
66
 
51
67
  $ sidtool --out <output file> <input file>
52
68
 
53
- The output can then be used to play back the music, for example in Sonic Pi:
69
+ The Ruby output can then be used to play back the music, for example in Sonic Pi:
54
70
 
55
71
  ```ruby
56
72
  load '<path to your output file from before>'
57
73
 
58
- previous_frame = 1
74
+ previous_frame = 0
59
75
  ::SYNTHS.each do |synth|
60
76
  current_frame = synth[0]
61
77
  frames_to_sleep = current_frame - previous_frame
data/bin/sidtool CHANGED
@@ -4,12 +4,17 @@ require 'mos6510'
4
4
  require 'optparse'
5
5
 
6
6
  DEFAULT_FRAMES_TO_PROCESS = 15000
7
+ EXPORTERS = {
8
+ 'ruby' => Sidtool::RubyFileWriter,
9
+ 'midi' => Sidtool::MidiFileWriter
10
+ }
7
11
 
8
12
  params = {}
9
13
  OptionParser.new do |parser|
10
14
  parser.banner = 'Usage: sidtool [options] <intputfile.sid>'
11
15
 
12
16
  parser.on('-i', '--info', 'Show file information')
17
+ parser.on('--format FORMAT', 'Output format, "ruby" (default) or "midi"')
13
18
  parser.on('-o', '--out FILENAME', 'Output file (Ruby array)')
14
19
  parser.on('-s', '--song NUMBER', Integer, 'Song number to process (defaults to the start song in the file)')
15
20
  parser.on('-f', '--frames NUMBER', Integer, "Number of frames to process (default #{DEFAULT_FRAMES_TO_PROCESS})")
@@ -32,6 +37,10 @@ output_file = params[:out]
32
37
  show_info = !!params[:info]
33
38
  raise 'Either provide -i or -o, or I have nothing to do!' unless output_file || show_info
34
39
 
40
+ format = params[:format] || EXPORTERS.keys.first
41
+ exporter_class = EXPORTERS[format]
42
+ raise "Invalid format: #{format}. Valid formats: #{EXPORTERS.keys.join(', ')}" unless exporter_class
43
+
35
44
  song = params[:song] || sid_file.start_song
36
45
  raise 'Song must be at least 1' if song < 1
37
46
  raise "File only has #{sid_file.songs} songs" if song > sid_file.songs
@@ -74,11 +83,5 @@ if output_file
74
83
 
75
84
  STDERR.puts("Processed #{frames} frames")
76
85
 
77
- File.open(output_file, 'w') do |file|
78
- file.puts '::SYNTHS = ['
79
- Sidtool::STATE.synths.each do |synth|
80
- file.puts synth.to_a.inspect + ','
81
- end
82
- file.puts ']'
83
- end
86
+ exporter_class.new(sid.synths_for_voices).write_to(output_file)
84
87
  end
@@ -0,0 +1,198 @@
1
+ module Sidtool
2
+ class MidiFileWriter
3
+ DeltaTime = Struct.new(:time) do
4
+ def bytes
5
+ quantity = time
6
+ seven_bit_segments = []
7
+ while true
8
+ seven_bit_segments << (quantity & 127)
9
+ quantity = quantity >> 7
10
+ break if quantity == 0
11
+ end
12
+ result = seven_bit_segments.reverse.map { |segment| segment | 128 }
13
+ result[-1] &= 127
14
+ result
15
+ end
16
+ end
17
+
18
+ TrackName = Struct.new(:name) do
19
+ def bytes
20
+ [
21
+ 0xFF, 0x03,
22
+ name.length,
23
+ *name.bytes
24
+ ]
25
+ end
26
+ end
27
+
28
+ TimeSignature = Struct.new(:numerator, :denominator_power_of_two, :clocks_per_metronome_click, :number_of_32th_nodes_per_24_clocks) do
29
+ def bytes
30
+ [
31
+ 0xFF, 0x58, 0x04,
32
+ numerator,
33
+ denominator_power_of_two,
34
+ clocks_per_metronome_click,
35
+ number_of_32th_nodes_per_24_clocks
36
+ ]
37
+ end
38
+ end
39
+
40
+ KeySignature = Struct.new(:sharps_or_flats, :is_major) do
41
+ def bytes
42
+ [
43
+ 0xFF, 0x59, 0x02,
44
+ sharps_or_flats,
45
+ is_major ? 0 : 1
46
+ ]
47
+ end
48
+ end
49
+
50
+ EndOfTrack = Struct.new(:nothing) do
51
+ def bytes
52
+ [
53
+ 0xFF, 0x2F, 0x00
54
+ ]
55
+ end
56
+ end
57
+
58
+ ProgramChange = Struct.new(:channel, :program_number) do
59
+ def bytes
60
+ raise "Channel too big: #{channel}" if channel > 15
61
+ raise "Program number is too big: #{program_number}" if program_number > 255
62
+ [
63
+ 0xC0 + channel,
64
+ program_number
65
+ ]
66
+ end
67
+ end
68
+
69
+ NoteOn = Struct.new(:channel, :key) do
70
+ def bytes
71
+ raise "Channel too big: #{channel}" if channel > 15
72
+ raise "Key is too big: #{key}" if key > 255
73
+ [
74
+ 0x90 + channel,
75
+ key,
76
+ 40 # Default velocity
77
+ ]
78
+ end
79
+ end
80
+
81
+ NoteOff = Struct.new(:channel, :key) do
82
+ def bytes
83
+ raise "Channel too big: #{channel}" if channel > 15
84
+ raise "Key is too big: #{key}" if key > 255
85
+ [
86
+ 0x80 + channel,
87
+ key,
88
+ 40 # Default velocity
89
+ ]
90
+ end
91
+ end
92
+
93
+ def initialize(synths_for_voices)
94
+ @synths_for_voices = synths_for_voices
95
+ end
96
+
97
+ def write_to(path)
98
+ tracks = @synths_for_voices.map { |synths| build_track(synths) }
99
+
100
+ File.open(path, 'wb') do |file|
101
+ write_header(file)
102
+ tracks.each_with_index { |track, index| write_track(file, track, "Voice #{index + 1}") }
103
+ end
104
+ end
105
+
106
+ def build_track(synths)
107
+ waveforms = [:tri, :saw, :pulse, :noise]
108
+
109
+ track = []
110
+ current_frame = 0
111
+ synths.each do |synth|
112
+ channel = waveforms.index(synth.waveform) || raise("Unknown waveform #{synth.waveform}")
113
+ track << DeltaTime[synth.start_frame - current_frame]
114
+ track << NoteOn[channel, synth.tone]
115
+ current_frame = synth.start_frame
116
+
117
+ current_tone = synth.tone
118
+ synth.controls.each do |start_frame, tone|
119
+ track << DeltaTime[start_frame - current_frame]
120
+ track << NoteOff[channel, current_tone]
121
+ track << DeltaTime[0]
122
+ track << NoteOn[channel, tone]
123
+ current_tone = tone
124
+ current_frame = start_frame
125
+ end
126
+
127
+ end_frame = [current_frame, synth.start_frame + (FRAMES_PER_SECOND * (synth.attack + synth.decay + synth.sustain_length)).to_i].max
128
+ track << DeltaTime[end_frame - current_frame]
129
+ track << NoteOff[channel, current_tone]
130
+
131
+ current_frame = end_frame
132
+ end
133
+
134
+ track
135
+ end
136
+
137
+ private
138
+ def write_header(file)
139
+ # Type
140
+ file << 'MThd'
141
+
142
+ # Length
143
+ write_uint32(file, 6)
144
+
145
+ # Format
146
+ write_uint16(file, 1)
147
+
148
+ # Number of tracks
149
+ write_uint16(file, 3)
150
+
151
+ # Division
152
+ # Default tempo is 120 BPM - 120 quarter-notes per minute. Which is 2 quarter-notes per second. If we then define
153
+ # 25 ticks per quarter-note, we end up with a timing of 50 ticks per second.
154
+ write_uint16(file, 25)
155
+ end
156
+
157
+ def write_track(file, track, name)
158
+ track_with_metadata = [
159
+ DeltaTime[0], TrackName[name],
160
+ DeltaTime[0], TimeSignature[4, 2, 24, 8],
161
+ DeltaTime[0], KeySignature[0, 0],
162
+
163
+ DeltaTime[0], ProgramChange[0, 1], # Triangular - maps to piano
164
+ DeltaTime[0], ProgramChange[1, 25], # Saw - maps to guitar
165
+ DeltaTime[0], ProgramChange[2, 33], # Pulse - maps to bass
166
+ DeltaTime[0], ProgramChange[3, 41] # Noise - maps to strings
167
+ ] +
168
+ track +
169
+ [
170
+ DeltaTime[0], EndOfTrack[]
171
+ ]
172
+ track_bytes = track_with_metadata.flat_map(&:bytes)
173
+
174
+ # Type
175
+ file << 'MTrk'
176
+
177
+ # Length
178
+ write_uint32(file, track_bytes.length)
179
+
180
+ file << track_bytes.pack('c' * track_bytes.length)
181
+ end
182
+
183
+ def write_uint32(file, value)
184
+ bytes = [(value >> 24) & 255, (value >> 16) & 255, (value >> 8) & 255, value & 255]
185
+ file << bytes.pack('cccc')
186
+ end
187
+
188
+ def write_uint16(file, value)
189
+ bytes = [(value >> 8) & 255, value & 255]
190
+ file << bytes.pack('cc')
191
+ end
192
+
193
+ def write_byte(file, value)
194
+ bytes = [value & 255]
195
+ file << bytes.pack('c')
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,17 @@
1
+ module Sidtool
2
+ class RubyFileWriter
3
+ def initialize(synths_for_voices)
4
+ @synths_for_voices = synths_for_voices
5
+ end
6
+
7
+ def write_to(path)
8
+ File.open(path, 'w') do |file|
9
+ file.puts '::SYNTHS = ['
10
+ @synths_for_voices.flatten.sort_by(&:start_frame).each do |synth|
11
+ file.puts synth.to_a.inspect + ','
12
+ end
13
+ file.puts ']'
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/sidtool/sid.rb CHANGED
@@ -2,7 +2,6 @@ module Sidtool
2
2
  class Sid
3
3
  def initialize
4
4
  @voices = [Voice.new, Voice.new, Voice.new]
5
- @synths = []
6
5
 
7
6
  @frequency_low = @frequency_high = 0
8
7
  @pulse_low = @pulse_high = 0
@@ -44,5 +43,9 @@ module Sidtool
44
43
  def stop!
45
44
  @voices.each(&:stop!)
46
45
  end
46
+
47
+ def synths_for_voices
48
+ @voices.map(&:synths)
49
+ end
47
50
  end
48
51
  end
data/lib/sidtool/state.rb CHANGED
@@ -1,11 +1,9 @@
1
1
  module Sidtool
2
2
  class State
3
3
  attr_accessor :current_frame
4
- attr_accessor :synths
5
4
 
6
5
  def initialize
7
6
  @current_frame = 0
8
- @synths = []
9
7
  end
10
8
  end
11
9
  end
data/lib/sidtool/synth.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  module Sidtool
2
2
  class Synth
3
- attr_writer :waveform
4
- attr_writer :attack
5
- attr_writer :decay
6
- attr_writer :release
3
+ attr_reader :start_frame
4
+ attr_accessor :waveform
5
+ attr_accessor :attack
6
+ attr_accessor :decay
7
+ attr_reader :sustain_length
8
+ attr_accessor :release
9
+ attr_reader :controls
7
10
 
8
11
  def initialize(start_frame)
9
12
  @start_frame = start_frame
@@ -48,10 +51,13 @@ module Sidtool
48
51
  end
49
52
 
50
53
  def to_a
51
- tone = sid_frequency_to_nearest_midi(@frequency)
52
54
  [@start_frame, tone, @waveform, @attack.round(3), @decay.round(3), @sustain_length.round(3), @release.round(3), @controls]
53
55
  end
54
56
 
57
+ def tone
58
+ sid_frequency_to_nearest_midi(@frequency)
59
+ end
60
+
55
61
  private
56
62
  def sid_frequency_to_nearest_midi(sid_frequency)
57
63
  actual_frequency = sid_frequency_to_actual_frequency(sid_frequency)
@@ -1,3 +1,3 @@
1
1
  module Sidtool
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.5'
3
3
  end
data/lib/sidtool/voice.rb CHANGED
@@ -7,41 +7,43 @@ module Sidtool
7
7
  attr_writer :control_register
8
8
  attr_writer :attack_decay
9
9
  attr_writer :sustain_release
10
+ attr_reader :synths
10
11
 
11
12
  def initialize
12
13
  @frequency_low = @frequency_high = 0
13
14
  @pulse_low = @pulse_high = 0
14
15
  @attack_decay = @sustain_release = 0
15
16
  @control_register = 0
16
- @synth = nil
17
+ @current_synth = nil
18
+ @synths = []
17
19
  end
18
20
 
19
21
  def finish_frame
20
22
  if gate
21
- if @synth&.released?
22
- @synth.stop!
23
- @synth = nil
23
+ if @current_synth&.released?
24
+ @current_synth.stop!
25
+ @current_synth = nil
24
26
  end
25
27
 
26
28
  if frequency > 0
27
- if !@synth
28
- @synth = Synth.new(STATE.current_frame)
29
- STATE.synths << @synth
29
+ if !@current_synth
30
+ @current_synth = Synth.new(STATE.current_frame)
31
+ @synths << @current_synth
30
32
  end
31
- @synth.frequency = frequency
32
- @synth.waveform = waveform
33
- @synth.attack = attack
34
- @synth.decay = decay
35
- @synth.release = release
33
+ @current_synth.frequency = frequency
34
+ @current_synth.waveform = waveform
35
+ @current_synth.attack = attack
36
+ @current_synth.decay = decay
37
+ @current_synth.release = release
36
38
  end
37
39
  else
38
- @synth&.release!
40
+ @current_synth&.release!
39
41
  end
40
42
  end
41
43
 
42
44
  def stop!
43
- @synth&.stop!
44
- @synth = nil
45
+ @current_synth&.stop!
46
+ @current_synth = nil
45
47
  end
46
48
 
47
49
  private
data/lib/sidtool.rb CHANGED
@@ -2,6 +2,8 @@ require 'sidtool/version'
2
2
 
3
3
  module Sidtool
4
4
  require 'sidtool/file_reader'
5
+ require 'sidtool/ruby_file_writer'
6
+ require 'sidtool/midi_file_writer'
5
7
  require 'sidtool/synth'
6
8
  require 'sidtool/voice'
7
9
  require 'sidtool/sid'
data/sidtool.gemspec CHANGED
@@ -12,13 +12,15 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = 'https://github.com/olefriis/sidtool'
13
13
  spec.license = 'MIT'
14
14
 
15
+ spec.required_ruby_version = '>= 2.3'
16
+
15
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
18
  f.match(%r{^(test|spec|features)/})
17
19
  end
18
20
  spec.executables = 'sidtool'
19
21
  spec.require_paths = ['lib']
20
22
 
21
- spec.add_dependency 'mos6510', '~> 0.1.0'
23
+ spec.add_dependency 'mos6510', '~> 0.1.2'
22
24
  spec.add_development_dependency 'bundler', '~> 2.0'
23
25
  spec.add_development_dependency 'rake', '~> 10.0'
24
26
  spec.add_development_dependency 'rspec', '~> 3.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidtool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ole Friis Østergaard
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-01 00:00:00.000000000 Z
11
+ date: 2022-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mos6510
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.0
19
+ version: 0.1.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.0
26
+ version: 0.1.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +80,7 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.12.2
83
- description:
83
+ description:
84
84
  email:
85
85
  - olefriis@gmail.com
86
86
  executables:
@@ -101,6 +101,8 @@ files:
101
101
  - bin/sidtool
102
102
  - lib/sidtool.rb
103
103
  - lib/sidtool/file_reader.rb
104
+ - lib/sidtool/midi_file_writer.rb
105
+ - lib/sidtool/ruby_file_writer.rb
104
106
  - lib/sidtool/sid.rb
105
107
  - lib/sidtool/state.rb
106
108
  - lib/sidtool/synth.rb
@@ -111,7 +113,7 @@ homepage: https://github.com/olefriis/sidtool
111
113
  licenses:
112
114
  - MIT
113
115
  metadata: {}
114
- post_install_message:
116
+ post_install_message:
115
117
  rdoc_options: []
116
118
  require_paths:
117
119
  - lib
@@ -119,15 +121,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
119
121
  requirements:
120
122
  - - ">="
121
123
  - !ruby/object:Gem::Version
122
- version: '0'
124
+ version: '2.3'
123
125
  required_rubygems_version: !ruby/object:Gem::Requirement
124
126
  requirements:
125
127
  - - ">="
126
128
  - !ruby/object:Gem::Version
127
129
  version: '0'
128
130
  requirements: []
129
- rubygems_version: 3.0.1
130
- signing_key:
131
+ rubygems_version: 3.3.3
132
+ signing_key:
131
133
  specification_version: 4
132
134
  summary: Convert SID tunes to other formats
133
135
  test_files: []