public List <Byte> MakeXM() { List <Byte> output = new List <byte>(); foreach (char c in "Extended Module: ") { output.Add((byte)c); } for (int i = 0; i < Math.Min(name.Length - 3, 20); i++) { output.Add((byte)name[i]); } while (output.Count < 0x25) { output.Add(0x20); } output.Add(0x1A); foreach (char c in "EPFExplorer") { output.Add((byte)c); } while (output.Count < 0x3A) { output.Add(0x00); } output.Add(0x04); output.Add(0x01); output.Add(0x14); output.Add(0x01); output.Add(0x00); output.Add(0x00); output.Add((byte)number_of_patterns_in_one_loop); output.Add((byte)(number_of_patterns_in_one_loop >> 8)); output.Add((byte)restartPosition); output.Add((byte)(restartPosition >> 8)); output.Add((byte)numchannels); output.Add((byte)(numchannels >> 8)); output.Add((byte)numpatterns); output.Add((byte)(numpatterns >> 8)); output.Add((byte)parentbinfile.samplecount); output.Add((byte)(parentbinfile.samplecount >> 8)); output.Add(0x01); output.Add(0x00); output.Add((byte)tempo); output.Add((byte)(tempo >> 8)); output.Add((byte)bpm); output.Add((byte)(bpm >> 8)); for (int i = 0; i < patternsInPlayingOrder.Count; i++) { output.Add((byte)patternsInPlayingOrder[i].index); } while (output.Count < 0x150) { output.Add(0x00); } foreach (Pattern p in patterns) { output.Add(0x09); output.Add(0x00); output.Add(0x00); output.Add(0x00); output.Add(0x00); output.Add((byte)p.number_of_rows); output.Add((byte)(p.number_of_rows >> 8)); output.Add((byte)(p.patternSize)); output.Add((byte)((p.patternSize) >> 8)); foreach (byte[] row in p.rows) { foreach (byte b in row) { output.Add(b); } } } //write instrument section string instrument_name = "instrument_"; string sample_name = "sample_"; for (int i = 0; i < samples.Count; i++) { sfxfile sample = (i >= 0 && i < samples.Count && samples[i] != null) ? samples[i] : null; output.Add(252); output.Add(0); output.Add(0); output.Add(0); int namelength = 0; foreach (char c in (instrument_name + i.ToString())) { output.Add((byte)c); namelength++; } while (namelength < 0x16) { output.Add(0x00); namelength++; } output.Add(0); output.Add(1); output.Add(0); output.Add(40); output.Add(0); output.Add(0); output.Add(0); for (int j = 0; j < 96; j++) { output.Add(0); } if (sample != null) { for (int j = 0; j < 24; j++) { output.Add(sample != null ? (byte)(sample.volenv.nodes[j] & 0xFF) : (byte)0); output.Add(sample != null ? (byte)(sample.volenv.nodes[j] >> 8) : (byte)0); } for (int j = 0; j < 24; j++) { output.Add(sample != null ? (byte)(sample.panenv.nodes[j] & 0xFF) : (byte)0); output.Add(sample != null ? (byte)(sample.panenv.nodes[j] >> 8) : (byte)0); } output.Add((byte)sample.volenv.count); output.Add((byte)sample.panenv.count); output.Add(sample.volenv.sustainPoint != 0xFF ? sample.volenv.sustainPoint : (byte)0); output.Add(sample.volenv.loopStart != 0xFF ? sample.volenv.loopStart : (byte)0); output.Add(sample.volenv.loopEnd != 0xFF ? sample.volenv.loopEnd : (byte)0); output.Add(sample.panenv.sustainPoint != 0xFF ? sample.panenv.sustainPoint : (byte)0); output.Add(sample.panenv.loopStart != 0xFF ? sample.panenv.loopStart : (byte)0); output.Add(sample.panenv.loopEnd != 0xFF ? sample.panenv.loopEnd : (byte)0); output.Add((byte)( (sample.volenv.count > 0 ? 1 : 0) | (sample.volenv.sustainPoint < sample.volenv.count ? 2 : 0) | (sample.volenv.loopStart < sample.volenv.count && sample.volenv.loopEnd < sample.volenv.count ? 4 : 0) )); output.Add((byte)( (sample.panenv.count > 0 ? 1 : 0) | (sample.panenv.sustainPoint < sample.panenv.count ? 2 : 0) | (sample.panenv.loopStart < sample.panenv.count && sample.panenv.loopEnd < sample.panenv.count ? 4 : 0) )); output.Add(0); output.Add(0); output.Add(0); output.Add(0); output.Add(0); output.Add(0); } else { for (int j = 0; j < 96 + 16; j++) { output.Add(0); } } for (int j = 0; j < 11; j++) { output.Add(0); } short[] pcm = sample != null?sample.ConvertToPCM() : new short[0] { }; output.Add((byte)((pcm.Length * 2) & 0xFF)); output.Add((byte)(((pcm.Length * 2) >> 8) & 0xFF)); output.Add((byte)(((pcm.Length * 2) >> 16) & 0xFF)); output.Add((byte)(((pcm.Length * 2) >> 24) & 0xFF)); if (sample != null) { output.Add((byte)((sample.loopstart * 4) & 0xFF)); output.Add((byte)(((sample.loopstart * 4) >> 8) & 0xFF)); output.Add((byte)(((sample.loopstart * 4) >> 16) & 0xFF)); output.Add((byte)(((sample.loopstart * 4) >> 24) & 0xFF)); output.Add((byte)(((sample.loopend * 4) - 0x10) & 0xFF)); output.Add((byte)(((sample.loopend * 4) >> 8) & 0xFF)); output.Add((byte)(((sample.loopend * 4) >> 16) & 0xFF)); output.Add((byte)(((sample.loopend * 4) >> 24) & 0xFF)); } else { for (int j = 0; j < 8; j++) { output.Add(0); } } output.Add(sample != null ? sample.defaultvol : (byte)0); output.Add(sample != null ? (byte)sample.finetune : (byte)0); output.Add((byte)(0x10 | (sample != null && sample.loopstart != 0xFFFFFFFF && sample.loopend != 0xFFFFFFFF ? 1 : 0))); output.Add(sample != null ? sample.defaultpan : (byte)0x80); output.Add(sample != null ? (byte)sample.transpose : (byte)0); output.Add(0); namelength = 0; foreach (char c in (sample_name + i.ToString())) { output.Add((byte)c); namelength++; } while (namelength < 0x16) { output.Add(0x00); namelength++; } short old = 0; for (int j = 0; j < pcm.Length; j++) { short n = (short)(pcm[j] - old); output.Add((byte)(n & 0xFF)); output.Add((byte)((n >> 8) & 0xFF)); old = pcm[j]; } } return(output); }