package com.netthreads.osc.note.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; import com.google.inject.Singleton; import com.netthreads.osc.network.ClientServerTest; /** * Note panel and bar matrix model. * */ @Singleton public class NoteModelImpl implements NoteModel { private static final Logger logger = LoggerFactory.getLogger(ClientServerTest.class); public static final int COUNT_BARS = 16; public static final int COUNT_BARS_RESET = COUNT_BARS - 1; public static final int COUNT_NOTES = 8; public static final int COUNT_PANELS = 4; private int bar; private boolean[][][] matrix; private NoteDefinition[][] notes; private boolean[][] last; private NoteBuilder noteBuilder; /** * Create model. * */ @Inject public NoteModelImpl(NoteBuilder noteBuilder) { this.noteBuilder = noteBuilder; // Matrix of all notes. On or off. matrix = new boolean[COUNT_PANELS][COUNT_BARS][COUNT_NOTES]; initialiseMatrix(matrix); // The last notes played in each bar so we can switch them off when the // next bar is played. last = new boolean[COUNT_PANELS][COUNT_NOTES]; initialiseLast(last); // The note definitions contain MIDI note id and MIDI channel id. notes = new NoteDefinition[COUNT_PANELS][COUNT_NOTES]; initialiseNotes(notes); bar = COUNT_BARS_RESET; } /** * Initialise matrix. * * @param data * The note active array. */ private void initialiseMatrix(boolean data[][][]) { for (int i = 0; i < COUNT_PANELS; i++) { for (int j = 0; j < COUNT_BARS; j++) { for (int k = 0; k < COUNT_NOTES; k++) { data[i][j][k] = false; } } } } /** * Initialise last notes played. We need this to ensure we send notes off. * * @param data * The note active array. */ private void initialiseLast(boolean data[][]) { for (int i = 0; i < COUNT_PANELS; i++) { for (int j = 0; j < COUNT_NOTES; j++) { data[i][j] = false; } } } /** * Initialise notes. * * @param data * The note active array. */ private void initialiseNotes(NoteDefinition data[][]) { for (int i = 0; i < COUNT_PANELS; i++) { for (int j = 0; j < COUNT_NOTES; j++) { Integer note = MIDINoteDefinition.NOTES.get(AppNotes.APP_NOTES[j]); /** * Channels go 1..16 not 0..15 */ data[i][j] = new NoteDefinition(note, i + 1); } } } /** * Set note state. * * @param bar * The bar (across the matrix). * @param note * The note (up and down the matrix) * @param state * The state. */ public void setState(int panel, int bar, int note, boolean state) { matrix[panel][bar][note] = state; } /** * Get note state. * * @param bar * The bar (across the matrix). * @param note * The note (up and down the matrix) * * @return The current state. */ public boolean getState(int panel, int bar, int note) { return matrix[panel][bar][note]; } /** * Play bar. * * Fairly straightforward - silence last bar, play the next and so on... * * @param panel * * @return The bar played. */ @Override public int play() { // Mute last silenceBar(bar); // Cycle around the bars. bar = (bar + 1) % COUNT_BARS; playBar(bar); return bar; } /** * Get last bar played. * * @return The last bar played. */ @Override public int getPlayed() { return bar; } /** * Reset bar. * * We silence any last notes being played and reset bar positions. * */ @Override public void reset() { // Silence last notes. silenceBar(bar); initialiseLast(last); bar = COUNT_BARS_RESET; } /** * Silence a bar of notes from the model. * * @param bar * The bar to silence. */ public void silenceBar(int bar) { noteBuilder.begin(); for (int panel = 0; panel < COUNT_PANELS; panel++) { for (int note = 0; note < COUNT_NOTES; note++) { if (last[panel][note]) { NoteDefinition noteDefinition = notes[panel][note]; if (noteDefinition != null) { noteBuilder.note(noteDefinition); // Gdx.app.log("", "Note off " + panel + "," + note); } else { logger.debug("", "No Note for panel:" + panel + "," + bar + ",note:" + note); } // Reset last[panel][note] = false; } } } // End note noteBuilder.end(); } /** * Play a bar of notes from the model. * * @param bar * The bar to play. */ public void playBar(int bar) { noteBuilder.begin(); for (int panel = 0; panel < COUNT_PANELS; panel++) { for (int note = 0; note < COUNT_NOTES; note++) { if (matrix[panel][bar][note]) { NoteDefinition noteDefinition = notes[panel][note]; if (noteDefinition != null) { noteBuilder.note(noteDefinition); // Gdx.app.log("", "Note on " + panel + "," + note); } else { logger.debug("", "No note definition:" + panel + "," + bar + ",note:" + note); } // Make a note of note on panel. last[panel][note] = true; } } } // End note noteBuilder.end(); } /** * Return notes. * * @return The model notes. */ public NoteDefinition[][] getNotes() { return notes; } }