Skip to content

Commit

Permalink
Merge pull request #52 from Kiroto/music_optimizations
Browse files Browse the repository at this point in the history
Instrument player optimizations
  • Loading branch information
TechPizzaDev authored Oct 2, 2023
2 parents 9fa561f + 35c5dec commit fe32862
Show file tree
Hide file tree
Showing 10 changed files with 366 additions and 200 deletions.
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

0 comments on commit fe32862

Please sign in to comment.