sidtool 0.0.2 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +11 -0
 - data/Gemfile.lock +8 -8
 - data/README.md +30 -14
 - data/bin/sidtool +10 -7
 - data/lib/sidtool/midi_file_writer.rb +198 -0
 - data/lib/sidtool/ruby_file_writer.rb +17 -0
 - data/lib/sidtool/sid.rb +4 -1
 - data/lib/sidtool/state.rb +0 -2
 - data/lib/sidtool/synth.rb +11 -5
 - data/lib/sidtool/version.rb +1 -1
 - data/lib/sidtool/voice.rb +17 -15
 - data/lib/sidtool.rb +2 -0
 - data/sidtool.gemspec +3 -1
 - metadata +12 -10
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 18bb0264bfc225b9bf717f464da9e9abc46777a93d3edd5ef985244fcc7e609d
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 9a9b61aee40dadb92111f5cfc3b12e85db24f37c98f33d3981244aa8e04a1097
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 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. 
     | 
| 
       5 
     | 
    
         
            -
                  mos6510 (~> 0.1. 
     | 
| 
      
 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 ( 
     | 
| 
      
 12 
     | 
    
         
            +
                libv8-node (16.10.0.0-x86_64-darwin)
         
     | 
| 
       13 
13 
     | 
    
         
             
                method_source (0.9.2)
         
     | 
| 
       14 
     | 
    
         
            -
                mini_racer (0.2 
     | 
| 
       15 
     | 
    
         
            -
                  libv8 ( 
     | 
| 
       16 
     | 
    
         
            -
                mos6510 (0.1. 
     | 
| 
       17 
     | 
    
         
            -
                  mini_racer (~> 0.2 
     | 
| 
      
 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. 
     | 
| 
      
 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! 
     | 
| 
       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  
     | 
| 
       17 
     | 
    
         
            -
            players already exist - but instead  
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
      
 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 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 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  
     | 
| 
      
 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 =  
     | 
| 
      
 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 
     | 
    
         
            -
               
     | 
| 
       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
    
    
    
        data/lib/sidtool/synth.rb
    CHANGED
    
    | 
         @@ -1,9 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Sidtool
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Synth
         
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
       4 
     | 
    
         
            -
                 
     | 
| 
       5 
     | 
    
         
            -
                 
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
      
 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)
         
     | 
    
        data/lib/sidtool/version.rb
    CHANGED
    
    
    
        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 
     | 
    
         
            -
                  @ 
     | 
| 
      
 17 
     | 
    
         
            +
                  @current_synth = nil
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @synths = []
         
     | 
| 
       17 
19 
     | 
    
         
             
                end
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
       19 
21 
     | 
    
         
             
                def finish_frame
         
     | 
| 
       20 
22 
     | 
    
         
             
                  if gate
         
     | 
| 
       21 
     | 
    
         
            -
                    if @ 
     | 
| 
       22 
     | 
    
         
            -
                      @ 
     | 
| 
       23 
     | 
    
         
            -
                      @ 
     | 
| 
      
 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 !@ 
     | 
| 
       28 
     | 
    
         
            -
                        @ 
     | 
| 
       29 
     | 
    
         
            -
                         
     | 
| 
      
 29 
     | 
    
         
            +
                      if !@current_synth
         
     | 
| 
      
 30 
     | 
    
         
            +
                        @current_synth = Synth.new(STATE.current_frame)
         
     | 
| 
      
 31 
     | 
    
         
            +
                        @synths << @current_synth
         
     | 
| 
       30 
32 
     | 
    
         
             
                      end
         
     | 
| 
       31 
     | 
    
         
            -
                      @ 
     | 
| 
       32 
     | 
    
         
            -
                      @ 
     | 
| 
       33 
     | 
    
         
            -
                      @ 
     | 
| 
       34 
     | 
    
         
            -
                      @ 
     | 
| 
       35 
     | 
    
         
            -
                      @ 
     | 
| 
      
 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 
     | 
    
         
            -
                    @ 
     | 
| 
      
 40 
     | 
    
         
            +
                    @current_synth&.release!
         
     | 
| 
       39 
41 
     | 
    
         
             
                  end
         
     | 
| 
       40 
42 
     | 
    
         
             
                end
         
     | 
| 
       41 
43 
     | 
    
         | 
| 
       42 
44 
     | 
    
         
             
                def stop!
         
     | 
| 
       43 
     | 
    
         
            -
                  @ 
     | 
| 
       44 
     | 
    
         
            -
                  @ 
     | 
| 
      
 45 
     | 
    
         
            +
                  @current_synth&.stop!
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @current_synth = nil
         
     | 
| 
       45 
47 
     | 
    
         
             
                end
         
     | 
| 
       46 
48 
     | 
    
         | 
| 
       47 
49 
     | 
    
         
             
                private
         
     | 
    
        data/lib/sidtool.rb
    CHANGED
    
    
    
        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. 
     | 
| 
      
 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. 
     | 
| 
      
 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:  
     | 
| 
      
 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. 
     | 
| 
      
 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. 
     | 
| 
      
 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: ' 
     | 
| 
      
 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. 
     | 
| 
       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: []
         
     |