Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instrument player optimizations #52

Merged
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.adventurecraft.awakening.common;

import dev.adventurecraft.awakening.common.instruments.IInstrumentConfig;
import dev.adventurecraft.awakening.common.instruments.Note;
import dev.adventurecraft.awakening.extension.client.gui.screen.ExScreen;
import dev.adventurecraft.awakening.extension.world.ExWorld;
import it.unimi.dsi.fastutil.ints.IntArrayList;
Expand All @@ -10,27 +12,32 @@

public class AC_GuiMusicSheet extends Screen {

private String instrument;
private IntArrayList notesPlayed;
private final IInstrumentConfig instrument;
private final IntArrayList notesPlayed;
private String notesPlayedString;
private int spaceTaken;
private AC_MusicScriptEntry songPlayed;
private long timeToFade;

public AC_GuiMusicSheet(String instrument) {
public AC_GuiMusicSheet(IInstrumentConfig instrument) {
this.instrument = instrument;
this.notesPlayed = new IntArrayList();
this.notesPlayedString = "";
this.songPlayed = null;
}

@Override
public void tick() {
}

@Override
public void initVanillaScreen() {
}
public static final Note[] keyboardNotes = {
new Note('D', -1), // Keyboard 1
new Note('E', -1),
new Note('F', -1),
new Note('G', -1),
new Note('A', 0),
new Note('B', 0),
new Note('C', 0),
new Note('D', 0),
new Note('E', 0),
new Note('F', 0), // Keyboard 0
};

@Override
protected void keyPressed(char character, int key) {
Expand Down Expand Up @@ -65,7 +72,6 @@ protected void keyPressed(char character, int key) {

int totalSpaceTaken = this.spaceTaken + NOTE_SIZE;


if (totalSpaceTaken >= MAX_NOTE_SPACE) {
this.notesPlayed.clear();
this.notesPlayedString = "";
Expand All @@ -75,36 +81,17 @@ protected void keyPressed(char character, int key) {
this.spaceTaken += NOTE_SIZE;
this.notesPlayed.add(key);

if (key == Keyboard.KEY_1) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'D', shiftDown, 0.5F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "1";
} else if (key == Keyboard.KEY_2) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'E', false, 0.5F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "2";
} else if (key == Keyboard.KEY_3) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'F', shiftDown, 0.5F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "3";
} else if (key == Keyboard.KEY_4) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'G', shiftDown, 0.5F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "4";
} else if (key == Keyboard.KEY_5) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'A', shiftDown, 1.0F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "5";
} else if (key == Keyboard.KEY_6) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'B', false, 1.0F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "6";
} else if (key == Keyboard.KEY_7) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'C', shiftDown, 1.0F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "7";
} else if (key == Keyboard.KEY_8) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'D', shiftDown, 1.0F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "8";
} else if (key == Keyboard.KEY_9) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'E', false, 1.0F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "9";
} else if (key == Keyboard.KEY_0) {
MusicPlayer.playNoteFromEntity(this.client.world, this.client.player, this.instrument, 'F', shiftDown, 1.0F, 1.0F);
this.notesPlayedString = this.notesPlayedString + "0";
Note noteToPlay = keyboardNotes[key - Keyboard.KEY_1];
this.notesPlayedString += Keyboard.getKeyName(key);


if (noteToPlay != null) {
int totalShiftValue = this.instrument.getTuning();
if (noteIsSharp)
totalShiftValue += 1;
noteToPlay = noteToPlay.withShiftedValue(totalShiftValue);

MusicPlayer.playNoteFromEntity(this.client.player, this.instrument, noteToPlay, 1F);
}

AC_MusicScriptEntry entry = ((ExWorld) this.client.world).getMusicScripts().executeMusic(this.notesPlayedString);
Expand Down Expand Up @@ -173,8 +160,8 @@ private void drawSharp(int x, int note) {
this.blit((this.width - 205) / 2 + 36 + x, this.height - 59 - 2 - 48 + 46 - (note - 2) * 4 - 5, 16, 64, 12, 17);
}

public static void showUI(String var0) {
Minecraft.instance.openScreen(new AC_GuiMusicSheet(var0));
public static void showUI(IInstrumentConfig instrumentConfig) {
Minecraft.instance.openScreen(new AC_GuiMusicSheet(instrumentConfig));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package dev.adventurecraft.awakening.common;

import dev.adventurecraft.awakening.extension.entity.block.ExSignBlockEntity;
import dev.adventurecraft.awakening.common.instruments.IInstrumentConfig;
import dev.adventurecraft.awakening.common.instruments.SimpleInstrumentConfig;
import dev.adventurecraft.awakening.extension.entity.block.ExSongContainer;
import net.minecraft.block.Block;
import net.minecraft.entity.block.SignBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
Expand All @@ -10,26 +12,60 @@

public class AC_ItemInstrument extends Item {

String instrument;

protected AC_ItemInstrument(int var1, String var2) {
super(var1);
this.instrument = var2;
/**
* The sound's URI.
* To play, for example, resources/newsound/note/harp.ogg, the instrument would be <code>"note.harp"</code>.
*/
IInstrumentConfig instrument;

/**
* Creates a new instrument item.
*
* @param itemId The ID of the item.
* @param instrumentUri The instrument's sound URI. Default tuning is +3
*/
protected AC_ItemInstrument(int itemId, String instrumentUri) {
super(itemId);
this.instrument = new SimpleInstrumentConfig(instrumentUri);
}

/**
* Creates a new instrument item.
*
* @param itemId The ID of the item.
* @param instrumentUri The instrument's sound URI.
* @param noteOffset The offset of the instrument to be tuned to match with the pentagram
*/
protected AC_ItemInstrument(int itemId, String instrumentUri, int noteOffset) {
super(itemId);
this.instrument = new SimpleInstrumentConfig(instrumentUri, noteOffset);
}

/**
* Creates a new instrument item.
*
* @param itemId The ID of the item.
* @param instrumentConfig The instrument config that the instrument will use
*/
protected AC_ItemInstrument(int itemId, IInstrumentConfig instrumentConfig) {
super(itemId);
this.instrument = instrumentConfig;
}

@Override
public boolean useOnBlock(ItemStack var1, PlayerEntity var2, World world, int targetBlockX, int targetBlockY, int targetBlockZ, int var7) {
if (world.getBlockId(targetBlockX, targetBlockY, targetBlockZ) == Block.STANDING_SIGN.id) {
var targetSign = (SignBlockEntity) world.getBlockEntity(targetBlockX, targetBlockY, targetBlockZ);
((ExSignBlockEntity) targetSign).playSong(this.instrument);
public boolean useOnBlock(ItemStack stack, PlayerEntity player, World world, int x, int y, int z, int side) {
if (world.getBlockId(x, y, z) == Block.STANDING_SIGN.id) {
var targetSign = (SignBlockEntity) world.getBlockEntity(x, y, z);
((ExSongContainer) targetSign).playSong(this.instrument);
}

return false;
}

@Override
public ItemStack use(ItemStack var1, World var2, PlayerEntity var3) {
public ItemStack use(ItemStack stack, World world, PlayerEntity player) {
AC_GuiMusicSheet.showUI(this.instrument);
return var1;
return stack;
}
}
149 changes: 22 additions & 127 deletions src/main/java/dev/adventurecraft/awakening/common/MusicPlayer.java
Original file line number Diff line number Diff line change
@@ -1,143 +1,38 @@
package dev.adventurecraft.awakening.common;

import dev.adventurecraft.awakening.common.instruments.IInstrumentConfig;
import dev.adventurecraft.awakening.common.instruments.Note;
import net.minecraft.entity.Entity;
import net.minecraft.world.World;

public class MusicPlayer {

/**
* @param world The world in which the note will be played
* @param sourceEntity The entity from which the location will be taken to play the note
* @param instrumentString The instrument name from which the sound will be taken
* @param noteChar The note character from A to G
* @param isSharp Whether the note should be played half a step higher
* @param basePitchModifier How much should the pitch be altered for the given note
* @param volume The volume of this note
* @param world The world where the sound will be played
* @param x The X position in said world
* @param y The Y position in said world
* @param z The Z position in said world
* @param instrumentConfig The instrument to be used to play the note
* @param note The note to be played
* @param volume The volume that the note will be played at
*/
public static void playNoteFromEntity(World world, Entity sourceEntity, String instrumentString, char noteChar, boolean isSharp, float basePitchModifier, float volume) {
playNote(world, sourceEntity.x, sourceEntity.y, sourceEntity.z, instrumentString, noteChar, isSharp, basePitchModifier, volume);
public static void playNote(World world, double x, double y, double z, IInstrumentConfig instrumentConfig, Note note, float volume) {
playNote(world, x, y, z, instrumentConfig.getSoundString(note), instrumentConfig.getPitchModifier() * note.getPitch(), instrumentConfig.getVolumeModifier() * volume);
}

/**
* @param targetWorld The world in which the note will be played
* @param worldXPos The X position of the sound
* @param worldYPos The Y position of the sound
* @param worldZPos The Z position of the sound
* @param instrumentString The instrument name from which the sound will be taken
* @param noteChar The note character from A to G
* @param isSharp Whether the note should be played half a step higher
* @param basePitchModifier How much should the pitch be altered for the given note
* @param volume The volume of this note
* @param world The world where the sound will be played
* @param x The X position in said world
* @param y The Y position in said world
* @param z The Z position in said world
* @param soundURI The instrument to be used on playing the note
* @param pitchMod The note to be played
* @param volume The volume that the note will be played at
*/
public static void playNote(World targetWorld, double worldXPos, double worldYPos, double worldZPos, String instrumentString, char noteChar, boolean isSharp, float basePitchModifier, float volume) {
float noteFrequency = 1.189207F; // Mod to F# to be A
switch (noteChar) { // Mod to A to be whatever note was played
case 'A':
break;
case 'B':
noteFrequency *= 1.122462F;
break;
case 'C':
noteFrequency *= 1.189207F;
break;
case 'D':
noteFrequency *= 1.33484F;
break;
case 'E':
noteFrequency *= 1.498307F;
break;
case 'F':
noteFrequency *= 1.587401F;
break;
case 'G':
noteFrequency *= 1.781797F;
break;
default:
return;
}

if (isSharp) {
noteFrequency = (float) ((double) noteFrequency * 1.059463D); // Mod to the note that was played to give it half a step upwards
}

targetWorld.playSound(worldXPos, worldYPos, worldZPos, instrumentString, volume, noteFrequency * basePitchModifier);
}

/**
* @param targetWorld The world where the note will be played
* @param worldXPos The x position in the world where the note will be played
* @param worldYPos The y position in the world where the note will be played
* @param worldZPos The z position in the world where the note will be played
* @param instrumentString The instrument that will be played
* @param songString The string that contains the song
* @param noteIndex The note to be played
* @param volume The volume in which the song will be played
*/
public static void playNoteFromSong(World targetWorld, double worldXPos, double worldYPos, double worldZPos, String instrumentString, String songString, int noteIndex, float volume) {
int stringIterationIndex = 0; // Current index on the string iteration
int noteIterationIndex = 0; // Current note of the song
boolean isFlat = false;
boolean isSharp = false;
char noteToPlay = 'A';

float basePitchModifier;
char iterationChar;

// Count the octave changes before up to the current note
for (basePitchModifier = 1.0F; noteIterationIndex <= noteIndex && stringIterationIndex < songString.length(); ++stringIterationIndex) {
iterationChar = songString.charAt(stringIterationIndex);
if (iterationChar == '+') { // Increase the octave of the note
basePitchModifier *= 2.0F;
} else if (iterationChar == '-') { // Lower the octave of the note
basePitchModifier *= 0.5F;
} else if (iterationChar != '#' && iterationChar != 'b') { // Ignore sharps and flats
noteToPlay = iterationChar; // Set this as the current note
++noteIterationIndex;
}
}


// Check the next character for a sharp or a flat (if it can exist)
if (stringIterationIndex < songString.length()) {
iterationChar = songString.charAt(stringIterationIndex);
if (iterationChar == '#') {
isSharp = true;
} else if (iterationChar == 'b') {
isFlat = true;
}
}

// Translate all flats to sharps instead, by reducing its char value (or rolling over if it's A, the lowest ASCII).
if (isFlat) {
if (noteToPlay == 'A') {
basePitchModifier *= 0.5F;
noteToPlay = 'G';
} else {
--noteToPlay;
}

isSharp = true;
}

// Finally play that note
playNote(targetWorld, worldXPos, worldYPos, worldZPos, instrumentString, noteToPlay, isSharp, basePitchModifier, volume);
public static void playNote(World world, double x, double y, double z, String soundURI, float pitchMod, float volume) {
world.playSound(x, y, z, soundURI, volume, pitchMod);
}

/**
* @param songString The string representation of the song
* @return the amount of notes in the string
*/
public static int countNotes(String songString) {
int i = 0;

int noteCount;
for (noteCount = 0; i < songString.length(); ++i) {
char currentNote = songString.charAt(i);
if (currentNote != '+' && currentNote != '-' && currentNote != '#' && currentNote != 'b') {
++noteCount;
}
}

return noteCount;
public static void playNoteFromEntity(Entity entity, IInstrumentConfig instrumentConfig, Note note, float volume) {
playNote(entity.world, entity.x, entity.y, entity.z, instrumentConfig, note, volume);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.adventurecraft.awakening.common.instruments;

public interface IInstrumentConfig {
String getSoundString(Note note);

float getPitchModifier();

float getVolumeModifier();

int getTuning();
}
Loading