private void readGeneralInfo(BufferedInputStream in, Module module) throws IOException { // "Extended Module: " byte b[] = read(in, 17); if (!(new String(b)).equalsIgnoreCase("Extended Module: ")) { throw new IOException("This is not a xm file!"); } // Module name b = read(in, 20); module.setTitle(new String(b)); in.read(); // Tracker name b = read(in, 20); // version in.read(); in.read(); // Header size read(in, 4); // Song length (in pattern order table) int[] patorder = new int[make16Bit(read(in, 2))]; // Restart position module.setRestartPosition(make16Bit(read(in, 2))); // Number of channels (2,4,6,8,10,...,32) module.setChannelCount(make16Bit(read(in, 2))); // Number of patterns (max 128) module.setPatterns(new Pattern[make16Bit(read(in, 2))]); // Number of instruments (max 128) module.setInstruments(new Instrument[make16Bit(read(in, 2))]); // Flags: bit 0: 0 = Amiga frequency table; // 1 = Linear frequency table if ((make16Bit(read(in, 2)) & 0x1) == 0) module.setAmigaFreqTable(true); // Default tempo module.setTempo(make16Bit(read(in, 2))); // Default BPM module.setBpm(make16Bit(read(in, 2))); // Pattern order table b = read(in, 256); for (int i = 0; i < patorder.length; i++) { patorder[i] = b[i]; } module.setPatternOrder(patorder); }
private void readPattern(BufferedInputStream in, Pattern p) throws IOException { // Pattern header length read(in, 4); // Packing type (always 0) in.read(); // Number of rows in pattern (1...256) int rows = make16Bit(read(in, 2)); // Packed patterndata size int size = make16Bit(read(in, 2)); int data[]; if (size == 0) { data = new int[0]; } else { byte[] b = read(in, size); data = new int[size]; for (int i = 0; i < size; i++) { data[i] = b[i]; } } p.setData(data); p.setRows(rows); }
private void loadSample(BufferedInputStream in, Sample sample) throws IOException { // Sample length int sampleLength = make32Bit(read(in, 4)); // Sample loop start int loopStart = make32Bit(read(in, 4)); // Sample loop length int loopEnd = make32Bit(read(in, 4)); if (loopStart + loopEnd > sampleLength) loopEnd = (sampleLength) - loopStart; // Volume sample.setVolume(in.read()); // Finetune (signend byte -128...+127) sample.setFineTune((byte) in.read()); // Type: Bit 0-1: 0 = No loop, // 1 = Forward loop, // 2 = Ping-pong loop; // 4: 16-bit sampledata int loopType = in.read(); int sampleQuality = ((int) loopType & 0x10) != 0 ? 16 : 8; if ((loopType & 0x3) == 0 || loopEnd == 0) { // no looping loopStart = 0; loopEnd = sampleLength; loopType &= 0x10; } // Panning (0-255) sample.setPanning(in.read() & 0xff); // Relative note number (signed byte) sample.setRelativeNote((byte) in.read()); // Reserved in.read(); // Sample name read(in, 22); sample.setLength(sampleLength); sample.setLoopType(loopType); sample.setQuality(sampleQuality); sample.setLoopStart(loopStart); sample.setLoopEnd(loopEnd); }
public void readInstrument(BufferedInputStream in, Instrument instr) throws IOException { // Instrument size int size = make32Bit(read(in, 4)); // Instrument name read(in, 22); // Instrument type (always 0) // Note: not always 0 but it says so in the documents... in.read(); // Number of samples in instrument Sample[] sample = new Sample[make16Bit(read(in, 2))]; if (sample.length == 0) { read(in, size - 29); } else { // Sample header size int ssize = make32Bit(read(in, 4)); if (ssize != 40) { throw new IOException("samplesize != 40!"); } // Sample number for all notes instr.setSampleForNote(read(in, 96)); // Points for volume envelope byte[] volEnvData = read(in, 48); // Points for panning envelope byte[] panEnvData = read(in, 48); // Number of volume points int points = in.read(); Envelope volumeEnvelope = new Envelope(); volumeEnvelope.setData(makeEnvelopePoints(points, volEnvData)); // Number of panning points points = in.read(); Envelope panningEnvelope = new Envelope(); panningEnvelope.setData(makeEnvelopePoints(points, panEnvData)); // Volume sustain point volumeEnvelope.setSustainPosition(in.read()); // Volume loop start point volumeEnvelope.setLoopStart(in.read()); // Volume loop end point volumeEnvelope.setLoopEnd(in.read()); // Panning sustain point panningEnvelope.setSustainPosition(in.read()); // Panning loop start point panningEnvelope.setLoopStart(in.read()); // Panning loop end point panningEnvelope.setLoopEnd(in.read()); // Volume type: bit 0: on; 1: Sustain; 2: Loop volumeEnvelope.setType(in.read()); // Panning type: bit 0: on; 1: Sustain; 2: Loop panningEnvelope.setType(in.read()); // Vibrato type Vibrato vibrato = new Vibrato(); vibrato.setType(in.read()); // Vibrato sweep vibrato.setSweep(in.read()); // Vibrato depth vibrato.setDepth(in.read()); // Vibrato rate vibrato.setRate(in.read()); // Volume fadeout instr.setFadeout(make16Bit(read(in, 2))); // reserved read(in, 22); for (int i = 0; i < sample.length; i++) { sample[i] = new Sample(); loadSample(in, sample[i]); } for (int i = 0; i < sample.length; i++) { loadSampleData(in, sample[i]); } instr.setPanningEnvelope(panningEnvelope); instr.setVolumeEnvelope(volumeEnvelope); instr.setVibrato(vibrato); instr.setSamples(sample); } }
public static final byte[] read(BufferedInputStream in, int len) throws IOException { byte[] b = new byte[len]; for (int i = 0; i < len; i += in.read(b, i, len - i)) ; return b; }