use of pl.asie.charset.api.tape.IDataStorage in project Charset by CharsetMC.
the class TileRecordPlayer method activate.
public boolean activate(EntityPlayer player, EnumFacing side, EnumHand hand, Vec3d hitPos) {
if (player.isSneaking() && side.getAxis() != EnumFacing.Axis.Y) {
if (!world.isRemote) {
player.openGui(ModCharset.instance, GuiHandlerCharset.RECORD_PLAYER, getWorld(), getPos().getX(), getPos().getY(), getPos().getZ());
}
return true;
}
Vec3d realPos = hitPos.subtract(0.5, 0.5, 0.5).rotateYaw((float) (getFacing().getHorizontalAngle() * Math.PI / 180));
if (side == EnumFacing.UP) {
if (realPos.x > -0.075 && realPos.z > -0.25 && !getStack().isEmpty()) {
if (realPos.x > 0.4) {
if (!world.isRemote) {
setState(TraitRecordPlayer.State.STOPPED);
}
return true;
} else {
if (player.isSneaking()) {
// TODO: Store state, allow for recording turning off
if (getState() == TraitRecordPlayer.State.PAUSED) {
if (!world.isRemote) {
setState(TraitRecordPlayer.State.PLAYING);
markBlockForUpdate();
}
return true;
} else if (getState() == TraitRecordPlayer.State.PLAYING) {
if (!world.isRemote) {
setState(TraitRecordPlayer.State.PAUSED);
markBlockForUpdate();
}
return true;
} else if (getState() == TraitRecordPlayer.State.RECORDING) {
return true;
}
} else {
if (!world.isRemote) {
if (getState() == TraitRecordPlayer.State.STOPPED) {
setState(TraitRecordPlayer.State.PLAYING);
}
// 0.05f = 0.12f
// 0.25f = 0.35f
float fmul = 0.0085f;
float fsub = 0.05f;
float fstart = (CharsetAudioStorage.quartzDisc.getArmStartPosition(holder.getStack()) * fmul) - fsub;
float fend = (32f * fmul) - fsub;
// System.out.println(fstart + " . " + fend);
float newPos = 1f - ((float) (realPos.x - fstart) / (fend - fstart));
if (newPos < 0.0f)
newPos = 0.0f;
else if (newPos > 1.0f)
newPos = 1.0f;
IDataStorage storage = this.getStorage();
if (storage != null) {
storage.setPosition(Math.round((storage.getSize() - 1) * newPos));
updateProgressClient();
this.player.stopAudioPlayback();
}
markBlockForUpdate();
}
return true;
}
}
}
if (getStack().isEmpty() || (player.getHeldItem(hand).isEmpty() && player.isSneaking())) {
if (holder.activate(this, player, side, hand)) {
markBlockForUpdate();
return true;
}
}
}
return false;
}
use of pl.asie.charset.api.tape.IDataStorage in project Charset by CharsetMC.
the class TraitRecordPlayer method update.
public void update(World world, BlockPos blockPos) {
if (state != State.STOPPED && state != State.PAUSED) {
if (sourceId == null) {
sourceId = AudioUtils.start();
}
boolean found = false;
ItemStack stack = inventory.getStackInSlot(0);
if (!stack.isEmpty() && stack.hasCapability(CharsetAudioStorage.DATA_STORAGE, null)) {
IDataStorage storage = stack.getCapability(CharsetAudioStorage.DATA_STORAGE, null);
if (storage != null) {
found = true;
if (state == State.PLAYING) {
int sampleRate = getSampleRate();
byte[] data = new byte[sampleRate / (20 * 8)];
int len = storage.read(data, false);
AudioPacket packet = new AudioPacket(new AudioDataDFPWM(data, 50).setSourceId(sourceId), 1.0F);
boolean received = false;
for (EnumFacing facing : EnumFacing.VALUES) {
TileEntity tile = world.getTileEntity(blockPos.offset(facing));
if (tile != null && tile.hasCapability(Capabilities.AUDIO_RECEIVER, facing.getOpposite())) {
received |= tile.getCapability(Capabilities.AUDIO_RECEIVER, facing.getOpposite()).receive(packet);
}
}
if (!received) {
new AudioSinkBlock(world, blockPos).receive(packet);
}
packet.send();
if (len < data.length) {
setState(State.PAUSED);
}
} else if (state == State.RECORDING) {
// TODO: This should advance at a constant pace
int sampleRate = getSampleRate();
if (!receivedPacket.isEmpty()) {
int adLen = 0;
for (AudioPacket packet : receivedPacket) {
adLen = Math.max(adLen, packet.getData().getTime() * sampleRate / 1000);
}
boolean added = false;
byte[] audioData = new byte[adLen];
for (AudioPacket packet : receivedPacket) {
AudioData data = packet.getData();
if (data instanceof IAudioDataPCM && packet.getVolume() >= 0.01f) {
IAudioDataPCM pcm = (IAudioDataPCM) data;
int len = audioData.length * 50 / data.getTime();
if (len > 0) {
byte[] preEncodeOutput = AudioResampler.toSigned8(pcm.getSamplePCMData(), pcm.getSampleSize() * 8, 1, pcm.isSampleBigEndian(), pcm.isSampleSigned(), pcm.getSampleRate(), sampleRate, false);
if (preEncodeOutput != null) {
added = true;
if (packet.getVolume() >= 0.995f) {
// fast path - no byte->float->byte casting
for (int i = 0; i < Math.min(preEncodeOutput.length, audioData.length); i++) {
audioData[i] += preEncodeOutput[i];
}
} else {
for (int i = 0; i < Math.min(preEncodeOutput.length, audioData.length); i++) {
audioData[i] += (byte) Math.round(preEncodeOutput[i] * packet.getVolume());
}
}
}
}
}
}
if (added) {
if (recordDFPWM == null) {
recordDFPWM = new DFPWM();
}
byte[] dataOut = new byte[audioData.length / 8];
recordDFPWM.compress(dataOut, audioData, 0, 0, audioData.length / 8);
storage.write(dataOut);
}
}
}
}
}
if (!found) {
setState(State.STOPPED);
}
}
if (lastState != state) {
TileEntity tileEntity = world.getTileEntity(blockPos);
CharsetAudioStorage.packet.sendToWatching(new PacketDriveState((TileRecordPlayer) tileEntity, state), tileEntity);
if ((state == State.STOPPED || state == State.PAUSED) && lastState == State.PLAYING && sourceId != null) {
stopAudioPlayback();
}
}
lastState = state;
receivedPacket.clear();
}
use of pl.asie.charset.api.tape.IDataStorage in project Charset by CharsetMC.
the class TraitRecordPlayerOC method seek.
@Callback(doc = "function(duration:number):number -- Seeks the specified amount of seconds on the record. " + "Negative values for rewinding. Returns the number of seconds sought.")
public Object[] seek(Context context, Arguments args) {
if (hasReadyStorage()) {
int seekAmount = (int) Math.round(args.checkDouble(0) * getBytesPerSecond());
if (seekAmount == 0) {
return new Object[] { 0.0 };
} else {
IDataStorage storage = getStorage();
int oldPos = storage.getPosition();
int newPos = oldPos + seekAmount;
if (newPos < 0)
newPos = 0;
else if (newPos > storage.getSize())
newPos = storage.getSize();
storage.setPosition(newPos);
return new Object[] { (double) (newPos - oldPos) / getBytesPerSecond() };
}
} else {
return new Object[] { 0.0 };
}
}
use of pl.asie.charset.api.tape.IDataStorage in project Charset by CharsetMC.
the class TileRecordPlayer method setState.
public void setState(TraitRecordPlayer.State state) {
player.setState(state);
if (!isInvalid()) {
if (state == TraitRecordPlayer.State.STOPPED) {
spinLocation = 0;
IDataStorage storage = getStorage();
if (storage != null) {
storage.setPosition(0);
}
}
}
}
use of pl.asie.charset.api.tape.IDataStorage in project Charset by CharsetMC.
the class TileRecordPlayer method updateProgressClient.
private void updateProgressClient() {
float pos = 0f;
IDataStorage storage = getStorage();
if (storage != null) {
pos = ((float) storage.getPosition() / storage.getSize());
}
if (Math.abs(pos - progressClient) >= 0.0125f || (pos == 0f) != (progressClient == 0f)) {
CharsetAudioStorage.packet.sendToWatching(new PacketUpdateProgressClient(this), this);
progressClient = pos;
}
}
Aggregations