n65 0.5.0 → 1.0.0
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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +28 -0
- data/.gitignore +1 -1
- data/.rubocop.yml +125 -0
- data/Gemfile +3 -1
- data/README.md +3 -20
- data/Rakefile +15 -1
- data/bin/n65 +2 -0
- data/data/opcodes.yaml +39 -39
- data/everdrive_transfer/everdrive.rb +175 -0
- data/examples/pulse_chord.asm +1 -1
- data/examples/scales.asm +182 -0
- data/lib/n65/directives/ascii.rb +4 -19
- data/lib/n65/directives/bytes.rb +20 -35
- data/lib/n65/directives/dw.rb +22 -36
- data/lib/n65/directives/enter_scope.rb +14 -30
- data/lib/n65/directives/exit_scope.rb +7 -17
- data/lib/n65/directives/inc.rb +14 -30
- data/lib/n65/directives/incbin.rb +6 -24
- data/lib/n65/directives/ines_header.rb +66 -27
- data/lib/n65/directives/label.rb +8 -21
- data/lib/n65/directives/org.rb +9 -19
- data/lib/n65/directives/segment.rb +5 -19
- data/lib/n65/directives/space.rb +6 -18
- data/lib/n65/front_end.rb +36 -39
- data/lib/n65/instruction.rb +123 -159
- data/lib/n65/instruction_base.rb +6 -18
- data/lib/n65/memory_space.rb +51 -71
- data/lib/n65/opcodes.rb +3 -5
- data/lib/n65/parser.rb +20 -38
- data/lib/n65/regexes.rb +20 -21
- data/lib/n65/symbol_table.rb +58 -89
- data/lib/n65/version.rb +3 -1
- data/lib/n65.rb +120 -121
- data/n65.gemspec +17 -12
- data/nes_lib/nes.sym +2 -2
- data/spec/.rubocop.yml +4 -0
- data/spec/assembler_spec.rb +84 -0
- data/spec/lib/n65/memory_space_spec.rb +147 -0
- data/spec/lib/n65/symbol_table_spec.rb +291 -0
- data/utils/opcode_table_to_yaml.rb +65 -67
- data.tar.gz.sig +0 -0
- metadata +84 -41
- metadata.gz.sig +0 -0
- data/examples/music_driver.asm +0 -202
- data/test/test_memory_space.rb +0 -82
- data/test/test_symbol_table.rb +0 -238
- data/utils/midi/Makefile +0 -3
- data/utils/midi/c_scale.mid +0 -0
- data/utils/midi/convert +0 -0
- data/utils/midi/guitar.mid +0 -0
- data/utils/midi/include/event.h +0 -93
- data/utils/midi/include/file.h +0 -57
- data/utils/midi/include/helpers.h +0 -14
- data/utils/midi/include/track.h +0 -45
- data/utils/midi/lil_melody.mid +0 -0
- data/utils/midi/mi_feabhra.mid +0 -0
- data/utils/midi/midi_to_nes.rb +0 -204
- data/utils/midi/source/convert.cpp +0 -16
- data/utils/midi/source/event.cpp +0 -96
- data/utils/midi/source/file.cpp +0 -37
- data/utils/midi/source/helpers.cpp +0 -46
- data/utils/midi/source/track.cpp +0 -37
data/utils/midi/include/track.h
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#ifndef MIDI_TRACK_H
|
|
2
|
-
#define MIDI_TRACK_H
|
|
3
|
-
|
|
4
|
-
#include "event.h"
|
|
5
|
-
#include <vector>
|
|
6
|
-
|
|
7
|
-
namespace Midi {
|
|
8
|
-
|
|
9
|
-
/***
|
|
10
|
-
* Spec:
|
|
11
|
-
* MidiTrack = <midi_track_header_t> + <MidiEvent> [+ <MidiEvent> ...]
|
|
12
|
-
* midi_track_header_t = "MTrk" + <size (4 bytes)>
|
|
13
|
-
*
|
|
14
|
-
***/
|
|
15
|
-
|
|
16
|
-
typedef struct midi_track_header_t {
|
|
17
|
-
char cookie[4];
|
|
18
|
-
unsigned int size;
|
|
19
|
-
} __attribute__((packed)) midi_track_header_t;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class Track {
|
|
23
|
-
private:
|
|
24
|
-
unsigned int m_total_size;
|
|
25
|
-
midi_track_header_t m_header;
|
|
26
|
-
|
|
27
|
-
public:
|
|
28
|
-
Track(void);
|
|
29
|
-
~Track(void);
|
|
30
|
-
void init_from_file(FILE *fp);
|
|
31
|
-
std::vector<Event *> m_events;
|
|
32
|
-
|
|
33
|
-
void print_yaml(){
|
|
34
|
-
printf(" - :header: MTrk\n");
|
|
35
|
-
printf(" :total_size: %u\n", m_header.size);
|
|
36
|
-
printf(" :events:\n");
|
|
37
|
-
|
|
38
|
-
for(int i = 0; i < m_events.size(); i++){
|
|
39
|
-
m_events[i]->print_yaml();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
#endif
|
data/utils/midi/lil_melody.mid
DELETED
|
Binary file
|
data/utils/midi/mi_feabhra.mid
DELETED
|
Binary file
|
data/utils/midi/midi_to_nes.rb
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require 'yaml'
|
|
4
|
-
|
|
5
|
-
class MidiToNES
|
|
6
|
-
|
|
7
|
-
#### Custom Exceptions
|
|
8
|
-
class MidiFormatNotSupported < StandardError; end
|
|
9
|
-
|
|
10
|
-
#### Some Constants
|
|
11
|
-
NoteOff = 0x8
|
|
12
|
-
NoteOn = 0x9
|
|
13
|
-
|
|
14
|
-
#### A440 Tuning, and NES CPU speed in hz
|
|
15
|
-
Tuning = 440.0
|
|
16
|
-
CPU = 1789773.0
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
#### LSB Address registers of the APU, MSB is always 0x40
|
|
20
|
-
Pulse1Control = 0x00
|
|
21
|
-
Pulse1FT = 0x2
|
|
22
|
-
Pulse1CT = 0x3
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
####
|
|
26
|
-
## Initialize from a yaml file
|
|
27
|
-
def self.init_from_file(filename, bpm)
|
|
28
|
-
self.new(File.read(filename), bpm)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
####
|
|
33
|
-
## Initialize with a yaml string
|
|
34
|
-
def initialize(yaml_string, bpm)
|
|
35
|
-
@bpm = bpm.to_f
|
|
36
|
-
@midi_data = YAML.load(yaml_string)[:midi_file]
|
|
37
|
-
unless @midi_data[:format].zero?
|
|
38
|
-
fail(MidiFormatNotSupported, "Currently only supports format 0 Midi Files")
|
|
39
|
-
end
|
|
40
|
-
@ticks_per_quarter_note = @midi_data[:ticks_per_quarter_note]
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
####
|
|
45
|
-
## Write to binary file
|
|
46
|
-
def write_binary(filename)
|
|
47
|
-
binary = convert
|
|
48
|
-
File.open(filename, 'wb') do |fp|
|
|
49
|
-
fp.write(binary)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
####
|
|
55
|
-
## For now assume one track
|
|
56
|
-
def convert
|
|
57
|
-
tick_count = 1
|
|
58
|
-
events = []
|
|
59
|
-
|
|
60
|
-
track = @midi_data[:tracks].first
|
|
61
|
-
track[:events].each do |event|
|
|
62
|
-
|
|
63
|
-
delta, status, note, velocity = event.values_at(:delta, :status, :parameter1, :parameter2)
|
|
64
|
-
|
|
65
|
-
## The status byte contains both the Midi message type, and channel.
|
|
66
|
-
type = (status & 0b11110000) >> 4
|
|
67
|
-
channel = status & 0b00001111
|
|
68
|
-
|
|
69
|
-
## We only care about note on and off, and only care about channel 0 for now.
|
|
70
|
-
next unless type == NoteOn || type == NoteOff
|
|
71
|
-
next unless channel.zero?
|
|
72
|
-
|
|
73
|
-
## Update the total time
|
|
74
|
-
tick_count += delta
|
|
75
|
-
|
|
76
|
-
## Ok this is a note either turning on or off
|
|
77
|
-
if type == NoteOff || velocity.zero?
|
|
78
|
-
#event = {:start => tick_count, :note => note, :velocity => 0}
|
|
79
|
-
#events << event
|
|
80
|
-
else
|
|
81
|
-
event = {:start => tick_count, :note => note, :velocity => velocity}
|
|
82
|
-
events << event
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
## Finally sort event list by start time
|
|
87
|
-
events.sort! do |a, b|
|
|
88
|
-
a[:start] <=> b[:start]
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
## Now convert these events to a bytestream for our NES sound engine
|
|
92
|
-
events_to_byte_stream(events)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
####
|
|
97
|
-
## This converts a list of note events into a byte stream for updating NES APU registers
|
|
98
|
-
def events_to_byte_stream(events)
|
|
99
|
-
last_tick = 1
|
|
100
|
-
byte_stream = []
|
|
101
|
-
|
|
102
|
-
events.each do |event|
|
|
103
|
-
## Work out the delta again
|
|
104
|
-
delta = event[:start] - last_tick
|
|
105
|
-
byte_stream << midi_tick_to_vblank(delta) # Delta
|
|
106
|
-
byte_stream << pulse_control_value(event) # Value
|
|
107
|
-
if event[:velocity].zero?
|
|
108
|
-
#byte_stream << 0 # Off with 0 frequency timer
|
|
109
|
-
#byte_stream << 0
|
|
110
|
-
else
|
|
111
|
-
byte_stream << pulse_ft_value(event) # Value
|
|
112
|
-
byte_stream << pulse_ct_value(event) # Value
|
|
113
|
-
end
|
|
114
|
-
last_tick += delta
|
|
115
|
-
end
|
|
116
|
-
byte_stream.pack('C*')
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
####
|
|
121
|
-
## Given an event, produce a value for register nes.apu.pulse1.control
|
|
122
|
-
## DDLC VVVV
|
|
123
|
-
## Duty (D), envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)
|
|
124
|
-
def pulse_control_value(event)
|
|
125
|
-
## Start with 50% duty cycle, length counter halt is on
|
|
126
|
-
## Constant volume is On, and volume is determined by bit-reducing the event velocity to 4-bit
|
|
127
|
-
value = 0b10000111
|
|
128
|
-
|
|
129
|
-
#four_bit_max = (2**4 - 1)
|
|
130
|
-
#seven_bit_max = (2**7 - 1)
|
|
131
|
-
|
|
132
|
-
#volume_float = event[:velocity] / seven_bit_max.to_f
|
|
133
|
-
#volume_4_bit = (volume_float * four_bit_max).round & 0b00001111
|
|
134
|
-
|
|
135
|
-
#value | volume_4_bit
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
####
|
|
140
|
-
## Given an event, produce a value for register nes.apu.pulse1.ft
|
|
141
|
-
## TTTT TTTT
|
|
142
|
-
## This is the low byte of the timer, the higher few bits being in pulse1.ct
|
|
143
|
-
def pulse_ft_value(event)
|
|
144
|
-
midi_note_to_nes_timer(event[:note]) & 0xff
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
####
|
|
149
|
-
## Given an event, produce a value for register nes.apu.pulse1.ct
|
|
150
|
-
## LLLL LTTT
|
|
151
|
-
## This has the higher 3 bits of the timer, and L is the length counter.
|
|
152
|
-
## For now let's just use duration as the length counter.
|
|
153
|
-
def pulse_ct_value(event)
|
|
154
|
-
value = 0b11111000
|
|
155
|
-
|
|
156
|
-
## We will grab the high 3 bits of the 11-bit timer value now
|
|
157
|
-
timer_high_3bit = midi_note_to_nes_timer(event[:note]) & 0b11100000000
|
|
158
|
-
value | (timer_high_3bit >> 8)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
####
|
|
163
|
-
## Midi note to NES timer
|
|
164
|
-
def midi_note_to_nes_timer(midi_note)
|
|
165
|
-
frequency = Tuning * 2**((midi_note - 69) / 12.0)
|
|
166
|
-
timer = (CPU / (16 * frequency)) - 1
|
|
167
|
-
if timer > (2**11 - 1)
|
|
168
|
-
fail("midi note #{midi_note} is too big at #{timer}")
|
|
169
|
-
end
|
|
170
|
-
timer.round
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
####
|
|
175
|
-
## Convert a MIDI tick delta to an NES vblank delta.
|
|
176
|
-
def midi_tick_to_vblank(midi_tick)
|
|
177
|
-
quarter_note_in_seconds = 60 / @bpm
|
|
178
|
-
vblanks_per_quarter_note = quarter_note_in_seconds / (1/60.0)
|
|
179
|
-
tick_normalized = midi_tick / @ticks_per_quarter_note.to_f
|
|
180
|
-
vblanks = tick_normalized * vblanks_per_quarter_note
|
|
181
|
-
vblanks.round
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
if __FILE__ == $0
|
|
187
|
-
unless ARGV.size == 2
|
|
188
|
-
STDERR.puts("Usage #{$0} <bpm> <music.mid>")
|
|
189
|
-
exit(1)
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
bpm, midi_file = ARGV
|
|
193
|
-
|
|
194
|
-
## Run the midi file through my converter written in C++
|
|
195
|
-
IO.popen("./convert #{midi_file}") do |io|
|
|
196
|
-
midi_to_nes = MidiToNES.new(io.read, bpm.to_i)
|
|
197
|
-
midi_to_nes.write_binary('../../data.mus')
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#include <stdio.h>
|
|
2
|
-
#include "file.h"
|
|
3
|
-
|
|
4
|
-
int main(int argc, char **argv){
|
|
5
|
-
|
|
6
|
-
if(argc < 1){
|
|
7
|
-
printf("Need a midi file argument\n");
|
|
8
|
-
exit(1);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
Midi::File midi_file;
|
|
12
|
-
midi_file.init_from_file(argv[1]);
|
|
13
|
-
midi_file.print_yaml();
|
|
14
|
-
|
|
15
|
-
return 0;
|
|
16
|
-
}
|
data/utils/midi/source/event.cpp
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
#include "event.h"
|
|
2
|
-
|
|
3
|
-
namespace Midi {
|
|
4
|
-
|
|
5
|
-
////
|
|
6
|
-
// Default constructor
|
|
7
|
-
Event::Event(void) :
|
|
8
|
-
m_delta(0), m_size(0),
|
|
9
|
-
m_data_size(0), m_status(0),
|
|
10
|
-
m_meta_type(0), m_parameter1(0),
|
|
11
|
-
m_parameter2(0), m_data(NULL) { }
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
////
|
|
15
|
-
// Constructor to set specific fields
|
|
16
|
-
Event::Event(int delta, int status, int parameter1, int parameter2) :
|
|
17
|
-
m_delta(delta), m_size(4),
|
|
18
|
-
m_data_size(0), m_status(status),
|
|
19
|
-
m_meta_type(0), m_parameter1(parameter1),
|
|
20
|
-
m_parameter2(parameter2), m_data(NULL) { }
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
////
|
|
24
|
-
// Use a file pointer to initialize
|
|
25
|
-
void Event::init_from_file(FILE *fp, unsigned char last_status){
|
|
26
|
-
fpos_t saved_position;
|
|
27
|
-
unsigned int value_size;
|
|
28
|
-
// All types of events are preceeded by a uintvar delta time
|
|
29
|
-
m_delta = read_variable_length(fp, &value_size);
|
|
30
|
-
m_size += value_size;
|
|
31
|
-
|
|
32
|
-
// All types then have a status byte, unless they are reusing
|
|
33
|
-
// the previous status, get ready to rewind if this is the case.
|
|
34
|
-
fgetpos(fp, &saved_position);
|
|
35
|
-
fread(&m_status, sizeof(unsigned char), 1, fp);
|
|
36
|
-
m_size++;
|
|
37
|
-
|
|
38
|
-
if(!is_status_byte(m_status)){
|
|
39
|
-
// This is not a status byte, so it must be reusing the previous one, Rewind
|
|
40
|
-
m_status = last_status;
|
|
41
|
-
fsetpos(fp, &saved_position);
|
|
42
|
-
m_size--;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
switch(m_status){
|
|
46
|
-
case 0xFF: // Meta
|
|
47
|
-
// This will have a meta sub type
|
|
48
|
-
fread(&m_meta_type, sizeof(unsigned char), 1, fp);
|
|
49
|
-
m_size++;
|
|
50
|
-
// Now a variable size for data
|
|
51
|
-
m_data_size = read_variable_length(fp, &value_size);
|
|
52
|
-
m_size += value_size;
|
|
53
|
-
// Finally, read the meta data
|
|
54
|
-
m_data = malloc(sizeof(unsigned char) * m_data_size);
|
|
55
|
-
fread(m_data, sizeof(unsigned char), m_data_size, fp);
|
|
56
|
-
m_size += m_data_size;
|
|
57
|
-
break;
|
|
58
|
-
case 0xF0: // Sysex
|
|
59
|
-
case 0xF7: // Sysex
|
|
60
|
-
// Sysex data runs until the next 0xF0 or 0xF7, count how many byte to allocate, and rewind
|
|
61
|
-
fgetpos(fp, &saved_position);
|
|
62
|
-
while(m_status != fgetc(fp)){
|
|
63
|
-
m_data_size++;
|
|
64
|
-
}
|
|
65
|
-
fsetpos(fp, &saved_position);
|
|
66
|
-
|
|
67
|
-
m_data = malloc(sizeof(unsigned char) * m_data_size);
|
|
68
|
-
fread(m_data, sizeof(unsigned char), m_data_size, fp);
|
|
69
|
-
m_size += (m_data_size + 1);
|
|
70
|
-
fgetc(fp); // Throw away the end byte, although it counts for size
|
|
71
|
-
break;
|
|
72
|
-
default: // Midi
|
|
73
|
-
fread(&m_parameter1, sizeof(unsigned char), 1, fp);
|
|
74
|
-
fread(&m_parameter2, sizeof(unsigned char), 1, fp);
|
|
75
|
-
m_size += 2;
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
void Event::init_midi(int delta, int status, int parameter1, int parameter2){
|
|
82
|
-
m_delta = delta;
|
|
83
|
-
m_status = status;
|
|
84
|
-
m_parameter1 = parameter1;
|
|
85
|
-
m_parameter2 = parameter2;
|
|
86
|
-
m_size = 4;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Event::~Event(void){
|
|
91
|
-
if(m_data){
|
|
92
|
-
free(m_data);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
}
|
data/utils/midi/source/file.cpp
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
#include "file.h"
|
|
2
|
-
|
|
3
|
-
namespace Midi {
|
|
4
|
-
|
|
5
|
-
File::File(void){
|
|
6
|
-
m_header.cookie[0] = m_header.cookie[1] = m_header.cookie[2] = m_header.cookie[3] = 0;
|
|
7
|
-
m_header.size = 0;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
void File::init_from_file(const char *filename){
|
|
12
|
-
FILE *fp = fopen(filename, "rb");
|
|
13
|
-
fread(&m_header, sizeof(midi_header_t), 1, fp);
|
|
14
|
-
// Fix up this Big Endian stuff
|
|
15
|
-
m_header.size = swap_endian_32(m_header.size);
|
|
16
|
-
m_header.format = swap_endian_16(m_header.format);
|
|
17
|
-
m_header.track_count = swap_endian_16(m_header.track_count);
|
|
18
|
-
m_header.ticks_per_quarter_note = swap_endian_16(m_header.ticks_per_quarter_note);
|
|
19
|
-
|
|
20
|
-
// Read each track
|
|
21
|
-
Track *track;
|
|
22
|
-
for(int i = 0; i < m_header.track_count; i++){
|
|
23
|
-
track = new Track();
|
|
24
|
-
track->init_from_file(fp);
|
|
25
|
-
m_tracks.push_back(track);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
File::~File(void){
|
|
31
|
-
// Free all the midi tracks
|
|
32
|
-
for(unsigned int i = 0; i < m_tracks.size(); i++){
|
|
33
|
-
delete m_tracks[i];
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
#include "helpers.h"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
namespace Midi {
|
|
5
|
-
|
|
6
|
-
////
|
|
7
|
-
// I have eliminated any doubt that this function works on variable
|
|
8
|
-
// length uintvars up to 4 bytes.
|
|
9
|
-
unsigned int read_variable_length(FILE *fp, unsigned int *value_size) {
|
|
10
|
-
unsigned int value;
|
|
11
|
-
*value_size = 1;
|
|
12
|
-
|
|
13
|
-
if((value = fgetc(fp)) & 0x80){
|
|
14
|
-
unsigned char c;
|
|
15
|
-
value &= 0x7F;
|
|
16
|
-
do{
|
|
17
|
-
(*value_size)++;
|
|
18
|
-
value = (value << 7) + ((c = fgetc(fp)) & 0x7F);
|
|
19
|
-
} while (c & 0x80);
|
|
20
|
-
}
|
|
21
|
-
return(value);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
////
|
|
26
|
-
// Swap 4 bytes
|
|
27
|
-
int swap_endian_32(int big_endian){
|
|
28
|
-
register int little_endian;
|
|
29
|
-
little_endian = (big_endian & 0x000000FF);
|
|
30
|
-
little_endian = ((big_endian & 0x0000FF00) >> 0x08) | (little_endian << 0x08);
|
|
31
|
-
little_endian = ((big_endian & 0x00FF0000) >> 0x10) | (little_endian << 0x08);
|
|
32
|
-
little_endian = ((big_endian & 0xFF000000) >> 0x18) | (little_endian << 0x08);
|
|
33
|
-
return(little_endian);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
////
|
|
38
|
-
// Swap 2 bytes
|
|
39
|
-
short swap_endian_16(short big_endian){
|
|
40
|
-
register short little_endian;
|
|
41
|
-
little_endian = (big_endian & 0x00FF);
|
|
42
|
-
little_endian = ((big_endian & 0xFF00) >> 0x08) | (little_endian << 0x08);
|
|
43
|
-
return(little_endian);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
}
|
data/utils/midi/source/track.cpp
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
#include "track.h"
|
|
2
|
-
|
|
3
|
-
namespace Midi {
|
|
4
|
-
|
|
5
|
-
Track::Track(void){
|
|
6
|
-
m_header.cookie[0] = m_header.cookie[1] = m_header.cookie[2] = m_header.cookie[3] = 0;
|
|
7
|
-
m_header.size = 0;
|
|
8
|
-
m_total_size = 0;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
void Track::init_from_file(FILE *fp){
|
|
13
|
-
Event *track_event;
|
|
14
|
-
unsigned int bytes_read = 0;
|
|
15
|
-
unsigned char last_status = 0x0;
|
|
16
|
-
|
|
17
|
-
fread(&m_header, sizeof(midi_track_header_t), 1, fp);
|
|
18
|
-
m_header.size = swap_endian_32(m_header.size);
|
|
19
|
-
if(m_header.size == 0) return;
|
|
20
|
-
|
|
21
|
-
while(bytes_read < m_header.size){
|
|
22
|
-
track_event = new Event();
|
|
23
|
-
track_event->init_from_file(fp, last_status);
|
|
24
|
-
m_events.push_back(track_event);
|
|
25
|
-
last_status = track_event->status();
|
|
26
|
-
bytes_read += track_event->bytes_read();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
Track::~Track(void){
|
|
31
|
-
// Free all the track events
|
|
32
|
-
for(unsigned int i = 0; i < m_events.size(); i++){
|
|
33
|
-
delete m_events[i];
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
}
|