package xyz.suruatoel.tuxguitar.drumsheets; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.function.Consumer; import org.herac.tuxguitar.graphics.control.TGFactoryImpl; import org.herac.tuxguitar.io.base.TGSongReader; import org.herac.tuxguitar.io.base.TGSongReaderHandle; import org.herac.tuxguitar.io.base.TGSongWriter; import org.herac.tuxguitar.io.base.TGSongWriterHandle; import org.herac.tuxguitar.io.tg.TGSongReaderImpl; import org.herac.tuxguitar.io.tg.TGSongWriterImpl; import org.herac.tuxguitar.song.factory.TGFactory; import org.herac.tuxguitar.song.models.TGBeat; import org.herac.tuxguitar.song.models.TGMeasure; import org.herac.tuxguitar.song.models.TGNote; import org.herac.tuxguitar.song.models.TGSong; import org.herac.tuxguitar.song.models.TGTrack; import org.herac.tuxguitar.song.models.TGVoice; /** * Application to clean drumset tracks in TuxGuitar files. */ public class Drumsheets { /** * TuxGuitar factory */ private TGFactory factory; /** * TuxGuitar song reader */ private TGSongReader songReader; /** * TuxGuitar song writer */ private TGSongWriter songWriter; /** * Create a new drumsheet instance. */ public Drumsheets() { this.factory = new TGFactoryImpl(); this.songReader = new TGSongReaderImpl(); this.songWriter = new TGSongWriterImpl(); } /** * Read a tg file as TuxGuitar song. * * @param file TG file to read * @return TuxGuitar song * @throws IOException Failed to read file */ public TGSong readSong(File file) throws IOException { System.out.println(String.format("Reading song file: %s", file.getAbsolutePath())); try(InputStream is = new FileInputStream(file)) { TGSongReaderHandle songHandle = new TGSongReaderHandle(); songHandle.setFactory(this.factory); songHandle.setInputStream(is); this.songReader.read(songHandle); return songHandle.getSong(); } } /** * Write a TuxGuitar song as tg file. * * @param song TuxGuitar song to write * @param file File to write song to * @throws IOException Failed to write file */ public void writeSong(TGSong song, File file) throws IOException { System.out.println(String.format("Writing song file: %s", file.getAbsolutePath())); try(OutputStream os = new FileOutputStream(file)) { TGSongWriterHandle songHandle = new TGSongWriterHandle(); songHandle.setSong(song); songHandle.setOutputStream(os); this.songWriter.write(songHandle); } } /** * Get all drum tracks of a TuxGuitar song. * * @param song TuxGuitar song to get drum tracks of * @return List of TuxGuitar tracks */ public List getDrumTracks(TGSong song) { List drumTracks = new ArrayList<>(); Iterator it = song.getTracks(); while(it.hasNext()) { TGTrack track = it.next(); // TODO Use a more reliable way to detect drum track if(track.getName().equals("Drumkit")) { drumTracks.add(track); } } return drumTracks; } /** * Apply all (currently hard coded) fixes for all drum tracks of a song. * * @param song TuxGuitar song to fix drum tracks of */ public void fixDrums(TGSong song) { System.out.println("Fix drums"); for(TGTrack drumTrack : getDrumTracks(song)) { fixDrum(drumTrack); } } /** * Apply all (currently hard coded) fixes for a drum track. * * @param drumTrack TuxGuitar drum track to fix */ public void fixDrum(TGTrack drumTrack) { System.out.println(String.format("Fix drum track: %s", drumTrack.getName())); // Crash cymbals changeNoteString(drumTrack, 57, 1); changeNoteString(drumTrack, 49, 1); // China cymbal changeNoteString(drumTrack, 52, 1); // Hi-Hat changeNoteString(drumTrack, 46, 2); changeNoteString(drumTrack, 42, 2); // Ride cymbal changeNoteString(drumTrack, 51, 2); changeNoteString(drumTrack, 53, 2); // Snare drum fixDrumNote(drumTrack, 38, 40); changeNoteString(drumTrack, 40, 3); // Toms fixDrumNote(drumTrack, 50, 48); changeNoteString(drumTrack, 48, 4); fixDrumNote(drumTrack, 47, 45); changeNoteString(drumTrack, 45, 4); changeNoteString(drumTrack, 43, 5); changeNoteString(drumTrack, 41, 5); // Bass drum changeNoteString(drumTrack, 36, 6); } /** * Move a note of a track to a string. * * @param track TuxGuitar track to change note of * @param note Value of note to change * @param string String to move note to */ public void changeNoteString(TGTrack track, int note, int string) { // Check if target string exists if(string > track.stringCount()) { System.err.println( String.format( "Cannot move note %d to string %d, string doas not exist", note, string ) ); } eachNote( track, tgNote -> { if(tgNote.getValue() == note && tgNote.getString() != string) { System.out.println( String.format( "Move note %d from string %d to %d", tgNote.getValue(), tgNote.getString(), string ) ); tgNote.setString(string); } } ); } /** * Change a note to another note. * * @param track TuxGuitar track to change note of * @param sourceNote Value of note to change * @param targetNote Value to change note to */ public void fixDrumNote(TGTrack track, int sourceNote, int targetNote) { eachNote( track, note -> { if(note.getValue() == sourceNote) { System.out.println(String.format("Change note %d to %d", sourceNote, targetNote)); note.setValue(targetNote); } } ); } /** * Call a consumer for each note of a track. * * @param track TuxGuitar track to traverse notes of * @param consumer Consumer to call for each note */ private void eachNote(TGTrack track, Consumer consumer) { // Traverse all measures Iterator measureIt = track.getMeasures(); while(measureIt.hasNext()) { TGMeasure measure = measureIt.next(); // Traverse all beats for(TGBeat beat : measure.getBeats()) { // Traverse all voices for(int v=0; v 1) { targetFile = new File(args[1]); } else { targetFile = sourceFile; } // Create application instance Drumsheets sheet = new Drumsheets(); try { // Read file TGSong song = sheet.readSong(sourceFile); // Fix drumset sheet.fixDrums(song); // Write file sheet.writeSong(song, targetFile); } catch(IOException e) { System.err.println(e.getMessage()); System.exit(1); } } }