Skip to content

Commit 82b57f6

Browse files
committed
Initial commit
0 parents  commit 82b57f6

File tree

20 files changed

+706
-0
lines changed

20 files changed

+706
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
target/
2+
.idea/
3+
.mvn/
4+
.DS_Store
5+

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Conifer Productions Oy
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

pom.xml

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.coniferproductions.sevenator</groupId>
7+
<artifactId>sevenator</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
10+
<name>sevenator</name>
11+
<!-- FIXME change it to the project's website -->
12+
<url>http://www.example.com</url>
13+
14+
<properties>
15+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16+
<maven.compiler.release>17</maven.compiler.release>
17+
</properties>
18+
19+
<dependencyManagement>
20+
<dependencies>
21+
<dependency>
22+
<groupId>org.junit</groupId>
23+
<artifactId>junit-bom</artifactId>
24+
<version>5.11.0</version>
25+
<type>pom</type>
26+
<scope>import</scope>
27+
</dependency>
28+
</dependencies>
29+
</dependencyManagement>
30+
31+
<dependencies>
32+
<dependency>
33+
<groupId>org.junit.jupiter</groupId>
34+
<artifactId>junit-jupiter-api</artifactId>
35+
<scope>test</scope>
36+
</dependency>
37+
<!-- Optionally: parameterized tests support -->
38+
<dependency>
39+
<groupId>org.junit.jupiter</groupId>
40+
<artifactId>junit-jupiter-params</artifactId>
41+
<scope>test</scope>
42+
</dependency>
43+
</dependencies>
44+
45+
<build>
46+
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
47+
<plugins>
48+
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
49+
<plugin>
50+
<artifactId>maven-clean-plugin</artifactId>
51+
<version>3.4.0</version>
52+
</plugin>
53+
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
54+
<plugin>
55+
<artifactId>maven-resources-plugin</artifactId>
56+
<version>3.3.1</version>
57+
</plugin>
58+
<plugin>
59+
<artifactId>maven-compiler-plugin</artifactId>
60+
<version>3.13.0</version>
61+
</plugin>
62+
<plugin>
63+
<artifactId>maven-surefire-plugin</artifactId>
64+
<version>3.3.0</version>
65+
</plugin>
66+
<plugin>
67+
<artifactId>maven-jar-plugin</artifactId>
68+
<version>3.4.2</version>
69+
</plugin>
70+
<plugin>
71+
<artifactId>maven-install-plugin</artifactId>
72+
<version>3.1.2</version>
73+
</plugin>
74+
<plugin>
75+
<artifactId>maven-deploy-plugin</artifactId>
76+
<version>3.1.2</version>
77+
</plugin>
78+
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
79+
<plugin>
80+
<artifactId>maven-site-plugin</artifactId>
81+
<version>3.12.1</version>
82+
</plugin>
83+
<plugin>
84+
<artifactId>maven-project-info-reports-plugin</artifactId>
85+
<version>3.6.1</version>
86+
</plugin>
87+
</plugins>
88+
</pluginManagement>
89+
</build>
90+
</project>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package com.coniferproductions.sevenator;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Files;
5+
import java.nio.file.Paths;
6+
import java.util.List;
7+
import java.util.ArrayList;
8+
import java.nio.ByteOrder;
9+
10+
public class App {
11+
public static void main(String[] args) {
12+
System.out.println("System byte order = " + ByteOrder.nativeOrder());
13+
14+
Channel channel = new Channel(1);
15+
System.out.println("Channel value = " + channel);
16+
System.out.println(String.format("Channel = [%d, %d]", Channel.TYPE.first(), Channel.TYPE.last()));
17+
System.out.println("Channel contains -7? " + Channel.TYPE.contains(-7));
18+
System.out.println("Channel contains 10? " + Channel.TYPE.contains(10));
19+
20+
Channel channel1 = new Channel(1);
21+
Channel channel2 = new Channel(2);
22+
if (channel1.equals(channel2)) {
23+
System.out.println("Same channel.");
24+
} else {
25+
System.out.println("Different channel.");
26+
}
27+
28+
//RangedInteger ri = new RangedInteger(); // abstract class, can't instantiate
29+
//BadChannel bc = new BadChannel(10); // internally inconsistent, throws exception
30+
//Level level = new Level(100); // initial value out of range, throws exception
31+
32+
MIDINote middleC = new MIDINote(60);
33+
System.out.println("Middle C is MIDI note number " + middleC.value()
34+
+ ", or " + middleC);
35+
36+
for (int value = middleC.last(); value >= middleC.first(); value--) {
37+
MIDINote note = new MIDINote(value);
38+
MIDINote.octave = Octave.ROLAND;
39+
System.out.print(value + " = " + note + " / ");
40+
MIDINote.octave = Octave.YAMAHA;
41+
System.out.println(note);
42+
}
43+
System.out.println();
44+
45+
System.out.println(String.format("Level = [%d, %d]", Level.TYPE.first(), Level.TYPE.last()));
46+
Level level1 = new Level(50);
47+
Level level2 = new Level(50);
48+
if (level1.equals(level2)) {
49+
System.out.println("The levels are equal.");
50+
} else {
51+
System.out.println("The levels are not equal.");
52+
}
53+
54+
List<UInt8> data = new ArrayList<>();
55+
try {
56+
byte[] contents = Files.readAllBytes(Paths.get(args[0]));
57+
58+
for (byte b : contents) {
59+
int value = b & 0xff;
60+
data.add(new UInt8(value));
61+
}
62+
63+
System.out.printf("%02X ... %02X", contents[0], contents[contents.length - 1]);
64+
65+
Message message = Message.parse(data);
66+
System.out.printf("%nMessage information:%n");
67+
System.out.printf("payload = %d bytes%n%n", message.getPayload().size());
68+
69+
Header header = Header.parse(message.getPayload());
70+
System.out.println("Header: format = " + header.getFormat());
71+
System.out.println("byte count = " + header.getByteCount());
72+
System.out.println("channel = " + header.getChannel());
73+
74+
} catch (IOException ioe) {
75+
ioe.printStackTrace();
76+
}
77+
78+
/*
79+
for (UInt8 b : data) {
80+
System.out.print(String.format("%02x", b.value()));
81+
System.out.print(" ");
82+
}
83+
System.out.println();
84+
*/
85+
86+
Runtime runtime = Runtime.getRuntime();
87+
long totalMemory = runtime.totalMemory();
88+
long freeMemory = runtime.freeMemory();
89+
long usedMemory = totalMemory - freeMemory;
90+
System.out.println(String.format("Total memory: %10d", totalMemory));
91+
System.out.println(String.format("Free memory: %10d", freeMemory));
92+
System.out.println(String.format("Used memory: %10d", usedMemory));
93+
}
94+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.coniferproductions.sevenator;
2+
3+
public final class BadChannel extends RangedInteger {
4+
public BadChannel() {
5+
this(1);
6+
}
7+
8+
public BadChannel(int value) {
9+
super(16, 1, value);
10+
}
11+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.coniferproductions.sevenator;
2+
3+
public final class Channel extends RangedInteger {
4+
public Channel(int value) {
5+
super(1, 16, value);
6+
}
7+
8+
// No redefinition of equals() since it is in the superclass.
9+
10+
/*
11+
@Override
12+
public boolean equals(Object o) {
13+
// Identical references?
14+
if (o == this) {
15+
return true;
16+
}
17+
18+
// Correct type and non-null?
19+
if (!(o instanceof Channel)) return false;
20+
21+
// Cast to our type.
22+
Channel that = (Channel) o;
23+
24+
return RangedInteger.hasEqualFields(this, that);
25+
}
26+
*/
27+
28+
29+
// Make one instance of this class as a static member,
30+
// so that you don't need to make an instance whenever you call
31+
// first(), last() or contains().
32+
public static final Channel TYPE = new Channel(1);
33+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.coniferproductions.sevenator;
2+
3+
import java.util.List;
4+
5+
public class Header {
6+
public enum Format {
7+
VOICE(0),
8+
CARTRIDGE(9);
9+
10+
private final int format;
11+
12+
Format(int format) {
13+
this.format = format;
14+
}
15+
16+
public int format() {
17+
return this.format;
18+
}
19+
}
20+
21+
private int substatus; // 0=voice/cartridge, 1=parameter
22+
private Channel channel;
23+
private Format format;
24+
private Short byteCount; // 14-bit number distributed evenly over two bytes
25+
// voice=155 (00000010011011 = 0x009B, appears as "01 1B")
26+
// cartridge=4096 (01000000000000 = 0x1000, appears as "20 00")
27+
28+
public static Header parse(List<UInt8> data) {
29+
UInt8 byteCountMSB = data.get(2);
30+
UInt8 byteCountLSB = data.get(3);
31+
UInt8 channelByte = new UInt8(data.get(0).value() & 0b00001111);
32+
if (!Channel.TYPE.contains(channelByte.value() + 1)) {
33+
throw new IllegalArgumentException("MIDI channel must be 1...16");
34+
}
35+
36+
Header header = new Header();
37+
38+
UInt8 formatByte = data.get(1);
39+
if (formatByte.value() == 0) {
40+
header.format = Format.VOICE;
41+
} else if (formatByte.value() == 9) {
42+
header.format = Format.CARTRIDGE;
43+
} else {
44+
throw new IllegalArgumentException("Not a voice or a cartridge!");
45+
}
46+
47+
header.substatus = ((data.get(0).value() >> 4) & 0b00000111);
48+
header.channel = new Channel(channelByte.value() + 1);
49+
switch (header.format) {
50+
case VOICE:
51+
header.byteCount = 155;
52+
break;
53+
case CARTRIDGE:
54+
header.byteCount = 4069;
55+
break;
56+
}
57+
58+
return header;
59+
}
60+
61+
public Format getFormat() {
62+
return this.format;
63+
}
64+
65+
public Short getByteCount() {
66+
return this.byteCount;
67+
}
68+
69+
public Channel getChannel() {
70+
return this.channel;
71+
}
72+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.coniferproductions.sevenator;
2+
3+
public final class Level extends RangedInteger {
4+
public Level(int value) {
5+
super(0, 99, value);
6+
}
7+
8+
public static final Level TYPE = new Level(0);
9+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.coniferproductions.sevenator;
2+
3+
public final class MIDINote extends RangedInteger {
4+
public static Octave octave = Octave.ROLAND;
5+
6+
public MIDINote(int value) {
7+
super(0, 127, value);
8+
}
9+
10+
public String name() {
11+
final String[] names = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
12+
int octaveOffset = MIDINote.octave.offset();
13+
int noteValue = this.value();
14+
15+
int octaveNumber = noteValue / 12 + octaveOffset;
16+
String noteName = names[noteValue % 12];
17+
return noteName + Integer.toString(octaveNumber);
18+
}
19+
20+
@Override
21+
public String toString() {
22+
return this.name();
23+
}
24+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.coniferproductions.sevenator;
2+
3+
public final class MIDIVelocity extends RangedInteger {
4+
public MIDIVelocity(int value) {
5+
super(0, 127, value);
6+
}
7+
}

0 commit comments

Comments
 (0)