Skip to content

Commit

Permalink
fixed channel volume on Playback
Browse files Browse the repository at this point in the history
  • Loading branch information
klesun committed Aug 27, 2015
1 parent 58f0edc commit eaa2c2a
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 19 deletions.
Binary file modified shmidusic.jar
Binary file not shown.
3 changes: 1 addition & 2 deletions src/org/shmidusic/sheet_music/staff/Staff.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ public synchronized void remove(Chord chord) {

public void accordListChanged(int repaintAllFromIndex)
{
setFocusedIndex(limit(getFocusedIndex(), -1, chordList.size() - 1));
this.tactList = recalcTactList(); // TODO: maybe do some optimization using repaintAllFromIndex
}

Expand Down Expand Up @@ -156,7 +155,7 @@ public Staff clearStan() {
// getters

public Chord getFocusedAccord() {
if (this.getFocusedIndex() > -1) {
if (this.getFocusedIndex() > -1 && this.getFocusedIndex() < this.chordList.size()) {
return getChordList().get(getFocusedIndex());
} else {
return null;
Expand Down
4 changes: 3 additions & 1 deletion src/org/shmidusic/sheet_music/staff/chord/Chord.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ public Stream<Nota> notaStream(Predicate<Nota> filterLambda) {
return getNotaSet().stream().filter(filterLambda);
}

// TODO: add parameter to Chord: "explicitLength" and use it instead of our fake-note-pauses
/** @return stream of real notes... maybe should store pause list separately? */
public Stream<Nota> notaStream() {
return getNotaSet().stream();
return notaStream(n -> !n.isPause());
}

public long getEarliestKeydown() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class Channel extends AbstractModel implements Comparable<Channel> {
public Channel setIsMuted(Boolean value) { isMuted.set(value); return this; }

public Integer getInstrument() { return instrument.get(); }
public int getVolume() { return volume.get(); }
public Integer getVolume() { return volume.get(); }
public Boolean getIsMuted() { return isMuted.get(); }

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,10 @@ public StaffConfig reconstructFromJson(JSONObject jsObject) throws JSONException
}

public void syncSyntChannels() {
ShortMessage instrMess = new ShortMessage();
try {
for (int i = 0; i < getChannelList().size(); ++i) {
instrMess.setMessage(ShortMessage.PROGRAM_CHANGE, i, channelList.get(i).getInstrument(), 0);
DeviceEbun.getPlaybackReceiver().send(instrMess, -1);
}
} catch (InvalidMidiDataException exc) { System.out.println("Midi error, could not sync channel instruments!"); }
for (int i = 0; i < getChannelList().size(); ++i) {
DeviceEbun.setInstrument(i, channelList.get(i).getInstrument());
DeviceEbun.setVolume(i, channelList.get(i).getVolume());
}
}

public static void syncSyntChannels(AbstractModel c) { ((StaffConfig)c).syncSyntChannels(); }
Expand Down
12 changes: 10 additions & 2 deletions src/org/shmidusic/stuff/Midi/DeviceEbun.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class DeviceEbun {

// data1 of ShortMessage.CONTROL_CHANGE
final static int PAN = 10;
final static int VOLUME = 7;
final static short CONTROL_CHANGE_VOLUME = 7;
final static int RESET_ALL_CONTROLLERS = 121;

// the first byte (status)
Expand Down Expand Up @@ -131,11 +131,19 @@ public static Explain changeOutDevice(StaffConfig config) {
}

public static void setVolume(int channel, int value) {
sendMessage(ShortMessage.CONTROL_CHANGE, channel, VOLUME, value);
sendMessage(ShortMessage.CONTROL_CHANGE, channel, CONTROL_CHANGE_VOLUME, value);
}

public static void setInstrument(int channel, int value) {
sendMessage(ShortMessage.PROGRAM_CHANGE, channel, value, 0);
}

synchronized public static void openNota(INota nota)
{
if (openNotaSet.contains(nota)) {
closeNota(nota);
}

openNotaSet.add(nota);
if (nota.getChannel() != DRUM_CHANNEL) {
sendMessage(ShortMessage.NOTE_ON, nota.getChannel(), nota.getTune(), 63); // 63 volume seems kinda hacky
Expand Down
28 changes: 22 additions & 6 deletions src/org/shmidusic/stuff/Midi/SimpleMidiParser.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package org.shmidusic.stuff.Midi;

import org.shmidusic.sheet_music.staff.Staff;
import org.shmidusic.sheet_music.staff.chord.Chord;
import org.shmidusic.sheet_music.staff.chord.nota.Nota;
import org.shmidusic.sheet_music.staff.staff_config.Channel;
import org.jm.midi.SMF;
import org.jm.midi.Track;
import org.jm.midi.event.*;
import org.shmidusic.sheet_music.SheetMusic;
import org.shmidusic.sheet_music.staff.StaffComponent;
import org.shmidusic.stuff.tools.jmusic_integration.INota;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

// this class imitates MidiParser in org.jm package, but simpler and for midiana model
// cuz i realized it would be pain in the ass to reuse their, Phrase-s was bad designer decision imho
Expand All @@ -21,19 +28,28 @@ public static SMF sheetMusicToSmf(SheetMusic sheetMusic)
// TODO: take into account multiple Staff-s!
Staff staff = sheetMusic.staffList.get(0);

// tempo 480 - for tempo 120
// tempo 960 - for tempo 60 - taking it for base cuz it's really close to 1000: 960 beats are 1000 miliseconds
// 480 - for tempo 120
// 960 - for tempo 60 - taking it for base cuz it's really close to 1000: 960 beats are 1000 miliseconds
SMF smf = new SMF((short)1, (short)(60 * 960 / staff.getConfig().getTempo())); // 1 i think means nothing, and tempo should be 480 by convention probably

// setting tempo. i suspect TimeSig and KeySig have absolute no influence on how things sound
// just facultative information to ease parse for whoever gets this midi file in future
Function<Channel, Event> mapChannelInstrument = c -> new PChange(c.getInstrument().shortValue(), c.channelNumber.get().shortValue(), 0);
Function<Channel, Event> mapChannelVolume = c -> new CChange(DeviceEbun.CONTROL_CHANGE_VOLUME, c.getVolume().shortValue(), c.channelNumber.get().shortValue(), 0);

Function<Channel, Event> mapChannel = c -> new PChange(c.getInstrument().shortValue(), c.channelNumber.get().shortValue(), 0);
Set<Integer> usedChannels = staff.chordStream()
.map(c -> c.notaStream().map(INota::getChannel))
.flatMap(s -> s)
.distinct()
.collect(Collectors.toSet());

List<Channel> channels = staff.getConfig().channelList.get().stream()
.filter(c -> usedChannels.contains(c.channelNumber.get()))
.collect(Collectors.toList());

smf.getTrackList().add(new Track()
.addEvent(new TempoEvent(0, staff.getConfig().getTempo()))
.addEvent(new TimeSig(0, staff.getConfig().getTactSize().getNumerator(), staff.getConfig().getTactSize().getDenominator()))
.addEvents(staff.getConfig().channelList.get().stream().filter(c -> c.getInstrument() != 0).map(mapChannel))
.addEvents(channels.stream().map(mapChannelInstrument))
.addEvents(channels.stream().map(mapChannelVolume))
.addEvent(new KeySig(Math.abs(staff.getConfig().keySignature.get()), (int) Math.signum(staff.getConfig().keySignature.get())))
.addEvent(new EndTrack())
);
Expand Down

0 comments on commit eaa2c2a

Please sign in to comment.