Search in sources :

Example 1 with TimeMapper

use of com.xenoage.zong.io.midi.out.time.TimeMapper 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);
}
Also used : lombok.val(lombok.val) PitchedInstrument(com.xenoage.zong.core.instrument.PitchedInstrument) TimeMapper(com.xenoage.zong.io.midi.out.time.TimeMapper) DynamicsInterpretation(com.xenoage.zong.io.midi.out.dynamics.DynamicsInterpretation)

Aggregations

PitchedInstrument (com.xenoage.zong.core.instrument.PitchedInstrument)1 DynamicsInterpretation (com.xenoage.zong.io.midi.out.dynamics.DynamicsInterpretation)1 TimeMapper (com.xenoage.zong.io.midi.out.time.TimeMapper)1 lombok.val (lombok.val)1