use of com.xenoage.zong.core.instrument.PitchedInstrument in project Zong by Xenoage.
the class MidiChordPlayer method playNote.
/**
* Plays a single note.
*/
public void playNote(Pitch pitch, Instrument instrument, byte velocity) {
if (instrument instanceof PitchedInstrument)
setMidiprogram(((PitchedInstrument) instrument).getMidiProgram());
int midipitch = MidiTools.getNoteNumber(pitch);
channel.noteOn(midipitch, velocity);
final Pitch p = pitch;
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
stopSingleNote(p);
timer.cancel();
}
}, duration);
}
use of com.xenoage.zong.core.instrument.PitchedInstrument in project Zong by Xenoage.
the class Test72b method testTransposes.
@Test
public void testTransposes() {
for (int iPart : range(expectedTransposes.length)) {
Part part = score.getStavesList().getParts().get(iPart);
PitchedInstrument instrument = (PitchedInstrument) part.getFirstInstrument();
assertEquals("Part " + iPart, expectedTransposes[iPart], instrument.getTranspose());
}
}
use of com.xenoage.zong.core.instrument.PitchedInstrument in project Zong by Xenoage.
the class MidiConverter method convertToSequence.
private MidiSequence<T> convertToSequence() {
// compute mapping of staff indices to channel numbers
channelMap = createChannelMap(score);
// compute repetitions (repeat barlines, segnos, ...)
repetitions = RepetitionsFinder.findRepetitions(score);
// compute the mappings from application time to MIDI time
timeMap = new TimeMapper(score, repetitions, options.midiSettings.resolutionFactor).createTimeMap();
// find all dynamics
dynamics = DynamicsFinder.findDynamics(score, new DynamicsInterpretation(), repetitions);
// one track for each staff and one system track for program changes, tempos and so on,
// and another track for the metronome
int stavesCount = score.getStavesCount();
int tracksCount = stavesCount + 1;
Integer metronomeTrack = null;
if (options.metronome) {
metronomeTrack = tracksCount;
tracksCount++;
}
// resolution in ticks per quarter
resolution = score.getDivisions() * options.midiSettings.getResolutionFactor();
// init writer
writer.init(tracksCount, resolution);
// set MIDI programs and init volume and pan
for (val part : score.getStavesList().getParts()) {
val instrument = part.getFirstInstrument();
int partFirstStaff = score.getStavesList().getPartStaffIndices(part).getStart();
int channel = channelMap.getChannel(partFirstStaff);
if (channel != unused) {
if (instrument instanceof PitchedInstrument) {
val pitchedInstrument = (PitchedInstrument) instrument;
writer.writeProgramChange(systemTrackIndex, channel, 0, (pitchedInstrument).getMidiProgram());
}
writer.writeVolumeChange(systemTrackIndex, channel, 0, instrument.getVolume());
writer.writePanChange(systemTrackIndex, channel, 0, instrument.getPan());
}
}
// fill tracks
for (int iStaff : range(stavesCount)) {
int channel = channelMap.getChannel(iStaff);
if (channel == unused)
// no MIDI channel left for this staff
continue;
Staff staff = score.getStaff(iStaff);
int voicesCount = staff.getVoicesCount();
// first track is reserved; see declaration of tracksCount
int track = iStaff + 1;
for (int iRepetition : range(repetitions)) {
val rep = repetitions.get(iRepetition);
// TODO
int transpose = 0;
for (int iMeasure : range(rep.start.getMeasure(), rep.end.getMeasure())) {
if (iMeasure == score.getMeasuresCount())
continue;
Measure measure = staff.getMeasure(iMeasure);
for (int iVoice : range(measure.getVoices())) {
writeVoice(atVoice(iStaff, iMeasure, iVoice), iRepetition);
}
}
}
}
// write events for time mapping between the MIDI sequence and the score
if (options.addTimeEvents)
writePlaybackControlEvents();
// write metronome track
if (options.metronome)
writeMetronomeTrack(metronomeTrack);
return writer.finish(metronomeTrack, timeMap);
}
use of com.xenoage.zong.core.instrument.PitchedInstrument in project Zong by Xenoage.
the class InstrumentsReaderTest method testInstrumentChanges.
/**
* Read the file "InstrumentChanges.xml".
* It must contain 3 instruments, namely a Clarinet in B, an Alto Sax in Eb
* and a Trombone in C. Check also the transpositons and see if the instrument
* changes happen at the right positions.
*/
@Test
public void testInstrumentChanges() {
Score score = MusicXmlScoreFileInputTest.loadXMLTestScore("InstrumentChanges.xml");
Part part = score.getStavesList().getParts().get(0);
assertEquals(3, part.getInstruments().size());
// clarinet
PitchedInstrument instr0 = (PitchedInstrument) part.getInstruments().get(0);
assertEquals("Clarinet in Bb", instr0.getName());
assertEquals(new Integer(-1), instr0.getTranspose().getDiatonic());
assertEquals(-2, instr0.getTranspose().getChromatic());
// altosax
PitchedInstrument instr1 = (PitchedInstrument) part.getInstruments().get(1);
assertEquals("Alto Saxophone", instr1.getName());
assertEquals(new Integer(-5), instr1.getTranspose().getDiatonic());
assertEquals(-9, instr1.getTranspose().getChromatic());
// trombone
PitchedInstrument instr2 = (PitchedInstrument) part.getInstruments().get(2);
assertEquals("Trombone", instr2.getName());
assertEquals(new Integer(0), instr2.getTranspose().getDiatonic());
assertEquals(0, instr2.getTranspose().getChromatic());
// instrument changes in measures 1, 2 and 3
Measure measure = score.getMeasure(atMeasure(0, 1));
assertEquals(instr1, getInstrumentChangeAtBeat0(measure).getInstrument());
measure = score.getMeasure(atMeasure(0, 2));
assertEquals(instr2, getInstrumentChangeAtBeat0(measure).getInstrument());
measure = score.getMeasure(atMeasure(0, 3));
assertEquals(instr0, getInstrumentChangeAtBeat0(measure).getInstrument());
}
use of com.xenoage.zong.core.instrument.PitchedInstrument in project Zong by Xenoage.
the class ChannelMapper method createReusedChannels.
/**
* Share channel for parts with the same instrument (MIDI program).
* If none is left, the part is ignored (channel index = {@link ChannelMap#unused}).
* All unpitched parts get channel 10.
*/
private static int[] createReusedChannels(Score score) {
int[] staffChannels = new int[score.getStavesCount()];
int nextFreeChannel = 0;
HashMap<Integer, Integer> programToDeviceMap = map();
for (Part part : score.getStavesList().getParts()) {
boolean isPitched = isPitched(part);
// find channel
int channel;
if (isPitched) {
// pitched part: create new channel or reuse existing channel
val pitchedInstr = (PitchedInstrument) part.getFirstInstrument();
int program = pitchedInstr.getMidiProgram();
channel = notNull(programToDeviceMap.get(program), nextFreeChannel);
if (channel >= maxChannelsCount) {
// no more channel left for this part
channel = unused;
} else if (channel == nextFreeChannel) {
// new channel created: increment next channel number and remember program
// don't use channel 10
nextFreeChannel = nextFreeChannel + 1 + (nextFreeChannel + 1 == channel10 ? 1 : 0);
programToDeviceMap.put(program, channel);
}
} else {
// unpitched part: always use channel 10
channel = channel10;
}
// apply channel to all staves
for (int iStaff : score.getStavesList().getPartStaffIndices(part).getRange()) {
staffChannels[iStaff] = channel;
}
}
return staffChannels;
}
Aggregations