Merge pull request #27 from fluddokt/AudioTest

Addition/Edge Addition SampleSet
This commit is contained in:
Jeffrey Han
2015-03-01 13:20:15 -05:00
10 changed files with 138 additions and 50 deletions

View File

@@ -1033,14 +1033,17 @@ public class GameData {
* @param y the y coordinate * @param y the y coordinate
* @param hitSound the object's hit sound * @param hitSound the object's hit sound
*/ */
public void sliderTickResult(int time, int result, float x, float y, byte hitSound) { public void sliderTickResult(int time, int result, float x, float y, OsuHitObject hitObject, int repeats) {
int hitValue = 0; int hitValue = 0;
switch (result) { switch (result) {
case HIT_SLIDER30: case HIT_SLIDER30:
hitValue = 30; hitValue = 30;
incrementComboStreak(); incrementComboStreak();
changeHealth(1f); changeHealth(1f);
SoundController.playHitSound(hitSound); SoundController.playHitSound(
hitObject.getEdgeHitSoundType(repeats),
hitObject.getSampleSet(repeats),
hitObject.getAdditionSampleSet(repeats));
break; break;
case HIT_SLIDER10: case HIT_SLIDER10:
hitValue = 10; hitValue = 10;
@@ -1076,7 +1079,7 @@ public class GameData {
* @param isSpinner whether the hit object was a spinner * @param isSpinner whether the hit object was a spinner
*/ */
public void hitResult(int time, int result, float x, float y, Color color, public void hitResult(int time, int result, float x, float y, Color color,
boolean end, byte hitSound, boolean isSpinner) { boolean end, OsuHitObject hitObject, int repeats, boolean isSpinner) {
int hitValue = 0; int hitValue = 0;
boolean perfectHit = false; boolean perfectHit = false;
switch (result) { switch (result) {
@@ -1104,7 +1107,10 @@ public class GameData {
return; return;
} }
if (hitValue > 0) { if (hitValue > 0) {
SoundController.playHitSound(hitSound); SoundController.playHitSound(
hitObject.getEdgeHitSoundType(repeats),
hitObject.getSampleSet(repeats),
hitObject.getAdditionSampleSet(repeats));
/** /**
* [SCORE FORMULA] * [SCORE FORMULA]

View File

@@ -71,6 +71,9 @@ public class OsuHitObject {
/** Hit sound type (SOUND_* bitmask). */ /** Hit sound type (SOUND_* bitmask). */
private byte hitSound; private byte hitSound;
/** Hit sound addition (sampleSet, AdditionSampleSet, ?, ...). */
private byte[] addition;
/** Slider curve type (SLIDER_* constant). */ /** Slider curve type (SLIDER_* constant). */
private char sliderType; private char sliderType;
@@ -86,6 +89,12 @@ public class OsuHitObject {
/** Spinner end time (in ms). */ /** Spinner end time (in ms). */
private int endTime; private int endTime;
/** Edge Hit sound type (SOUND_* bitmask). */
private byte[] edgeHitSound;
/** Edge Hit sound addition (sampleSet, AdditionSampleSet). */
private byte[][] edgeAddition;
// additional v10+ parameters not implemented... // additional v10+ parameters not implemented...
// addition -> sampl:add:cust:vol:hitsound // addition -> sampl:add:cust:vol:hitsound
// edge_hitsound, edge_addition (sliders only) // edge_hitsound, edge_addition (sliders only)
@@ -156,8 +165,12 @@ public class OsuHitObject {
// type-specific fields // type-specific fields
if ((type & OsuHitObject.TYPE_CIRCLE) > 0) { if ((type & OsuHitObject.TYPE_CIRCLE) > 0) {
/* 'addition' not implemented. */ if (tokens.length > 5) {
String[] additionTokens = tokens[5].split(":");
addition = new byte[additionTokens.length];
for (int j = 0; j < additionTokens.length; j++)
this.addition[j] = Byte.parseByte(additionTokens[j]);
}
} else if ((type & OsuHitObject.TYPE_SLIDER) > 0) { } else if ((type & OsuHitObject.TYPE_SLIDER) > 0) {
// slider curve type and coordinates // slider curve type and coordinates
String[] sliderTokens = tokens[5].split("\\|"); String[] sliderTokens = tokens[5].split("\\|");
@@ -171,8 +184,22 @@ public class OsuHitObject {
} }
this.repeat = Integer.parseInt(tokens[6]); this.repeat = Integer.parseInt(tokens[6]);
this.pixelLength = Float.parseFloat(tokens[7]); this.pixelLength = Float.parseFloat(tokens[7]);
/* edge fields and 'addition' not implemented. */ if (tokens.length > 8) {
String[] edgeHitSoundTokens = tokens[8].split("\\|");
this.edgeHitSound = new byte[edgeHitSoundTokens.length];
for (int j = 0; j < edgeHitSoundTokens.length; j++) {
edgeHitSound[j] = Byte.parseByte(edgeHitSoundTokens[j]);
}
}
if (tokens.length > 9) {
String[] edgeAdditionTokens = tokens[9].split("\\|");
this.edgeAddition = new byte[edgeAdditionTokens.length][2];
for (int j = 0; j < edgeAdditionTokens.length; j++) {
String[] tedgeAddition = edgeAdditionTokens[j].split(":");
edgeAddition[j][0] = Byte.parseByte(tedgeAddition[0]);
edgeAddition[j][1] = Byte.parseByte(tedgeAddition[1]);
}
}
} else { //if ((type & OsuHitObject.TYPE_SPINNER) > 0) { } else { //if ((type & OsuHitObject.TYPE_SPINNER) > 0) {
// some 'endTime' fields contain a ':' character (?) // some 'endTime' fields contain a ':' character (?)
int index = tokens[5].indexOf(':'); int index = tokens[5].indexOf(':');
@@ -213,6 +240,16 @@ public class OsuHitObject {
*/ */
public byte getHitSoundType() { return hitSound; } public byte getHitSoundType() { return hitSound; }
/**
* Returns the edge hit sound type.
* @return the sound type (SOUND_* bitmask)
*/
public byte getEdgeHitSoundType(int i) {
if(edgeHitSound != null)
return edgeHitSound[i];
else return hitSound;
}
/** /**
* Returns the slider type. * Returns the slider type.
* @return the slider type (SLIDER_* constant) * @return the slider type (SLIDER_* constant)
@@ -301,4 +338,26 @@ public class OsuHitObject {
* Returns the number of extra skips on the combo colors. * Returns the number of extra skips on the combo colors.
*/ */
public int getComboSkip() { return (type >> TYPE_NEWCOMBO); } public int getComboSkip() { return (type >> TYPE_NEWCOMBO); }
/**
* Returns the Sample Set at i.
*/
public byte getSampleSet(int i) {
if (edgeAddition != null)
return edgeAddition[i][0];
if (addition != null)
return addition[0];
return 0;
}
/**
* Returns the Addition Sample Set at i.
*/
public byte getAdditionSampleSet(int i) {
if (edgeAddition != null)
return edgeAddition[i][1];
if (addition != null)
return addition[1];
return 0;
}
} }

View File

@@ -564,8 +564,8 @@ public class OsuParser {
// set combo info // set combo info
// - new combo: get next combo index, reset combo number // - new combo: get next combo index, reset combo number
// - else: maintain combo index, increase combo number // - else: maintain combo index, increase combo number
if (((hitObject.isNewCombo() || first) && !hitObject.isSpinner())) { if (hitObject.isNewCombo() || first) {
int skip = 1 + hitObject.getComboSkip(); int skip = (hitObject.isSpinner()?0:1) + hitObject.getComboSkip();
for (int i = 0; i < skip; i++) { for (int i = 0; i < skip; i++) {
comboIndex = (comboIndex + 1) % osu.combo.length; comboIndex = (comboIndex + 1) % osu.combo.length;
comboNumber = 1; comboNumber = 1;

View File

@@ -73,6 +73,9 @@ public enum HitSound implements SoundController.SoundComponent {
/** Current sample set. */ /** Current sample set. */
private static SampleSet currentSampleSet; private static SampleSet currentSampleSet;
/** Current default sample set. */
private static SampleSet currentDefaultSampleSet = SampleSet.NORMAL;
/** The file name. */ /** The file name. */
private String filename; private String filename;
@@ -112,25 +115,38 @@ public enum HitSound implements SoundController.SoundComponent {
} }
/** /**
* Sets the sample set to use when playing hit sounds. * Sets the default sample set to use when playing hit sounds.
* @param sampleSet the sample set ("None", "Normal", "Soft", "Drum") * @param sampleSet the sample set ("auto", "Normal", "Soft", "Drum")
*/ */
public static void setSampleSet(String sampleSet) { public static void setDefaultSampleSet(String sampleSet) {
currentSampleSet = null; currentDefaultSampleSet = SampleSet.NORMAL;
for (SampleSet ss : SampleSet.values()) { for (SampleSet ss : SampleSet.values()) {
if (sampleSet.equalsIgnoreCase(ss.getName())) { if (sampleSet.equalsIgnoreCase(ss.getName())) {
currentSampleSet = ss; currentDefaultSampleSet = ss;
return; return;
} }
} }
} }
/**
* Sets the default sample set to use when playing hit sounds.
* @param sampleSet the sample set (0:auto, 1:normal, 2:soft, 3:drum)
*/
public static void setDefaultSampleSet(byte sampleType) {
currentDefaultSampleSet = SampleSet.NORMAL;
for (SampleSet ss : SampleSet.values()) {
if (sampleType == ss.getIndex()) {
currentDefaultSampleSet = ss;
return;
}
}
}
/** /**
* Sets the sample set to use when playing hit sounds. * Sets the sample set to use when playing hit sounds.
* @param sampleType the sample set (0:none, 1:normal, 2:soft, 3:drum) * @param sampleType the sample set (0:auto, 1:normal, 2:soft, 3:drum)
*/ */
public static void setSampleSet(byte sampleType) { public static void setSampleSet(byte sampleType) {
currentSampleSet = null; currentSampleSet = currentDefaultSampleSet;
for (SampleSet ss : SampleSet.values()) { for (SampleSet ss : SampleSet.values()) {
if (sampleType == ss.getIndex()) { if (sampleType == ss.getIndex()) {
currentSampleSet = ss; currentSampleSet = ss;
@@ -138,4 +154,6 @@ public enum HitSound implements SoundController.SoundComponent {
} }
} }
} }
} }

View File

@@ -252,7 +252,7 @@ public class SoundController {
* Plays hit sound(s) using an OsuHitObject bitmask. * Plays hit sound(s) using an OsuHitObject bitmask.
* @param hitSound the hit sound (bitmask) * @param hitSound the hit sound (bitmask)
*/ */
public static void playHitSound(byte hitSound) { public static void playHitSound(byte hitSound, byte sampleSet, byte additionSampleSet) {
if (hitSound < 0) if (hitSound < 0)
return; return;
@@ -261,16 +261,16 @@ public class SoundController {
return; return;
// play all sounds // play all sounds
if (hitSound == OsuHitObject.SOUND_NORMAL) HitSound.setSampleSet(sampleSet);
playClip(HitSound.NORMAL.getClip(), volume); playClip(HitSound.NORMAL.getClip(), volume);
else {
if ((hitSound & OsuHitObject.SOUND_WHISTLE) > 0) HitSound.setSampleSet(additionSampleSet);
playClip(HitSound.WHISTLE.getClip(), volume); if ((hitSound & OsuHitObject.SOUND_WHISTLE) > 0)
if ((hitSound & OsuHitObject.SOUND_FINISH) > 0) playClip(HitSound.WHISTLE.getClip(), volume);
playClip(HitSound.FINISH.getClip(), volume); if ((hitSound & OsuHitObject.SOUND_FINISH) > 0)
if ((hitSound & OsuHitObject.SOUND_CLAP) > 0) playClip(HitSound.FINISH.getClip(), volume);
playClip(HitSound.CLAP.getClip(), volume); if ((hitSound & OsuHitObject.SOUND_CLAP) > 0)
} playClip(HitSound.CLAP.getClip(), volume);
} }
/** /**

View File

@@ -141,7 +141,7 @@ public class Circle implements HitObject {
data.hitResult( data.hitResult(
hitObject.getTime(), result, hitObject.getTime(), result,
hitObject.getX(), hitObject.getY(), hitObject.getX(), hitObject.getY(),
color, comboEnd, hitObject.getHitSoundType(), false color, comboEnd, hitObject, 0, false
); );
return true; return true;
} }
@@ -153,7 +153,6 @@ public class Circle implements HitObject {
public boolean update(boolean overlap, int delta, int mouseX, int mouseY) { public boolean update(boolean overlap, int delta, int mouseX, int mouseY) {
int time = hitObject.getTime(); int time = hitObject.getTime();
float x = hitObject.getX(), y = hitObject.getY(); float x = hitObject.getX(), y = hitObject.getY();
byte hitSound = hitObject.getHitSoundType();
int trackPosition = MusicController.getPosition(); int trackPosition = MusicController.getPosition();
int[] hitResultOffset = game.getHitResultOffsets(); int[] hitResultOffset = game.getHitResultOffsets();
@@ -161,17 +160,17 @@ public class Circle implements HitObject {
if (overlap || trackPosition > time + hitResultOffset[GameData.HIT_50]) { if (overlap || trackPosition > time + hitResultOffset[GameData.HIT_50]) {
if (isAutoMod) // "auto" mod: catch any missed notes due to lag if (isAutoMod) // "auto" mod: catch any missed notes due to lag
data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitSound, false); data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitObject, 0, false);
else // no more points can be scored, so send a miss else // no more points can be scored, so send a miss
data.hitResult(time, GameData.HIT_MISS, x, y, null, comboEnd, hitSound, false); data.hitResult(time, GameData.HIT_MISS, x, y, null, comboEnd, hitObject, 0, false);
return true; return true;
} }
// "auto" mod: send a perfect hit result // "auto" mod: send a perfect hit result
else if (isAutoMod) { else if (isAutoMod) {
if (Math.abs(trackPosition - time) < hitResultOffset[GameData.HIT_300]) { if (Math.abs(trackPosition - time) < hitResultOffset[GameData.HIT_300]) {
data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitSound, false); data.hitResult(time, GameData.HIT_300, x, y, color, comboEnd, hitObject, 0, false);
return true; return true;
} }
} }

View File

@@ -253,10 +253,14 @@ public class Slider implements HitObject {
if (currentRepeats % 2 == 0) { // last circle if (currentRepeats % 2 == 0) { // last circle
float[] lastPos = curve.pointAt(1); float[] lastPos = curve.pointAt(1);
data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result, data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result,
lastPos[0],lastPos[1], color, comboEnd, hitObject.getHitSoundType(), false); lastPos[0],lastPos[1], color, comboEnd,
hitObject, currentRepeats+1
, false);
} else { // first circle } else { // first circle
data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result, data.hitResult(hitObject.getTime() + (int) sliderTimeTotal, result,
hitObject.getX(), hitObject.getY(), color, comboEnd, hitObject.getHitSoundType(), false); hitObject.getX(), hitObject.getY(), color, comboEnd,
hitObject, currentRepeats+1
, false);
} }
return result; return result;
@@ -286,7 +290,9 @@ public class Slider implements HitObject {
data.addHitError(hitObject.getTime(), x,y,trackPosition - hitObject.getTime()); data.addHitError(hitObject.getTime(), x,y,trackPosition - hitObject.getTime());
sliderClickedInitial = true; sliderClickedInitial = true;
data.sliderTickResult(hitObject.getTime(), result, data.sliderTickResult(hitObject.getTime(), result,
hitObject.getX(), hitObject.getY(), hitObject.getHitSoundType()); hitObject.getX(), hitObject.getY(),
hitObject, currentRepeats
);
return true; return true;
} }
} }
@@ -315,7 +321,6 @@ public class Slider implements HitObject {
} }
} }
byte hitSound = hitObject.getHitSoundType();
int trackPosition = MusicController.getPosition(); int trackPosition = MusicController.getPosition();
int[] hitResultOffset = game.getHitResultOffsets(); int[] hitResultOffset = game.getHitResultOffsets();
int lastIndex = hitObject.getSliderX().length - 1; int lastIndex = hitObject.getSliderX().length - 1;
@@ -330,10 +335,10 @@ public class Slider implements HitObject {
if (isAutoMod) { // "auto" mod: catch any missed notes due to lag if (isAutoMod) { // "auto" mod: catch any missed notes due to lag
ticksHit++; ticksHit++;
data.sliderTickResult(time, GameData.HIT_SLIDER30, data.sliderTickResult(time, GameData.HIT_SLIDER30,
hitObject.getX(), hitObject.getY(), hitSound); hitObject.getX(), hitObject.getY(), hitObject, currentRepeats);
} else } else
data.sliderTickResult(time, GameData.HIT_MISS, data.sliderTickResult(time, GameData.HIT_MISS,
hitObject.getX(), hitObject.getY(), hitSound); hitObject.getX(), hitObject.getY(), hitObject, currentRepeats);
} }
// "auto" mod: send a perfect hit result // "auto" mod: send a perfect hit result
@@ -342,7 +347,7 @@ public class Slider implements HitObject {
ticksHit++; ticksHit++;
sliderClickedInitial = true; sliderClickedInitial = true;
data.sliderTickResult(time, GameData.HIT_SLIDER30, data.sliderTickResult(time, GameData.HIT_SLIDER30,
hitObject.getX(), hitObject.getY(), hitSound); hitObject.getX(), hitObject.getY(), hitObject, currentRepeats);
} }
} }
} }
@@ -411,17 +416,18 @@ public class Slider implements HitObject {
ticksHit++; ticksHit++;
if (currentRepeats % 2 > 0) // last circle if (currentRepeats % 2 > 0) // last circle
data.sliderTickResult(trackPosition, GameData.HIT_SLIDER30, data.sliderTickResult(trackPosition, GameData.HIT_SLIDER30,
hitObject.getSliderX()[lastIndex], hitObject.getSliderY()[lastIndex], hitSound); hitObject.getSliderX()[lastIndex], hitObject.getSliderY()[lastIndex],
hitObject, currentRepeats);
else // first circle else // first circle
data.sliderTickResult(trackPosition, GameData.HIT_SLIDER30, data.sliderTickResult(trackPosition, GameData.HIT_SLIDER30,
c[0], c[1], hitSound); c[0], c[1], hitObject, currentRepeats);
} }
// held during new tick // held during new tick
if (isNewTick) { if (isNewTick) {
ticksHit++; ticksHit++;
data.sliderTickResult(trackPosition, GameData.HIT_SLIDER10, data.sliderTickResult(trackPosition, GameData.HIT_SLIDER10,
c[0], c[1], (byte) -1); c[0], c[1], hitObject, currentRepeats);
} }
// held near end of slider // held near end of slider
@@ -431,9 +437,9 @@ public class Slider implements HitObject {
followCircleActive = false; followCircleActive = false;
if (isNewRepeat) if (isNewRepeat)
data.sliderTickResult(trackPosition, GameData.HIT_MISS, 0, 0, (byte) -1); data.sliderTickResult(trackPosition, GameData.HIT_MISS, 0, 0, hitObject, currentRepeats);
if (isNewTick) if (isNewTick)
data.sliderTickResult(trackPosition, GameData.HIT_MISS, 0, 0, (byte) -1); data.sliderTickResult(trackPosition, GameData.HIT_MISS, 0, 0, hitObject, currentRepeats);
} }
return false; return false;

View File

@@ -164,7 +164,7 @@ public class Spinner implements HitObject {
result = GameData.HIT_MISS; result = GameData.HIT_MISS;
data.hitResult(hitObject.getEndTime(), result, width / 2, height / 2, data.hitResult(hitObject.getEndTime(), result, width / 2, height / 2,
Color.transparent, true, (byte) -1, true); Color.transparent, true, hitObject, 0, true);
return result; return result;
} }

View File

@@ -449,7 +449,7 @@ public class Game extends BasicGameState {
beatLengthBase = beatLength = timingPoint.getBeatLength(); beatLengthBase = beatLength = timingPoint.getBeatLength();
else else
beatLength = beatLengthBase * timingPoint.getSliderMultiplier(); beatLength = beatLengthBase * timingPoint.getSliderMultiplier();
HitSound.setSampleSet(timingPoint.getSampleType()); HitSound.setDefaultSampleSet(timingPoint.getSampleType());
SoundController.setSampleVolume(timingPoint.getSampleVolume()); SoundController.setSampleVolume(timingPoint.getSampleVolume());
timingPointIndex++; timingPointIndex++;
} }
@@ -728,7 +728,7 @@ public class Game extends BasicGameState {
OsuTimingPoint timingPoint = osu.timingPoints.get(0); OsuTimingPoint timingPoint = osu.timingPoints.get(0);
if (!timingPoint.isInherited()) { if (!timingPoint.isInherited()) {
beatLengthBase = beatLength = timingPoint.getBeatLength(); beatLengthBase = beatLength = timingPoint.getBeatLength();
HitSound.setSampleSet(timingPoint.getSampleType()); HitSound.setDefaultSampleSet(timingPoint.getSampleType());
SoundController.setSampleVolume(timingPoint.getSampleVolume()); SoundController.setSampleVolume(timingPoint.getSampleVolume());
timingPointIndex++; timingPointIndex++;
} }

View File

@@ -1264,7 +1264,7 @@ public class SongMenu extends BasicGameState {
OsuFile osu = MusicController.getOsuFile(); OsuFile osu = MusicController.getOsuFile();
Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString())); Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString()));
OsuParser.parseHitObjects(osu); OsuParser.parseHitObjects(osu);
HitSound.setSampleSet(osu.sampleSet); HitSound.setDefaultSampleSet(osu.sampleSet);
MultiClip.destroyExtraClips(); MultiClip.destroyExtraClips();
((Game) game.getState(Opsu.STATE_GAME)).setRestart(Game.Restart.NEW); ((Game) game.getState(Opsu.STATE_GAME)).setRestart(Game.Restart.NEW);
game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black)); game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));