Search in sources :

Example 1 with IDataStorage

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;
}
Also used : IDataStorage(pl.asie.charset.api.tape.IDataStorage) Vec3d(net.minecraft.util.math.Vec3d)

Example 2 with IDataStorage

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();
}
Also used : AudioSinkBlock(pl.asie.charset.lib.audio.types.AudioSinkBlock) EnumFacing(net.minecraft.util.EnumFacing) IDataStorage(pl.asie.charset.api.tape.IDataStorage) TileEntity(net.minecraft.tileentity.TileEntity) AudioDataDFPWM(pl.asie.charset.lib.audio.types.AudioDataDFPWM) DFPWM(pl.asie.charset.lib.audio.codec.DFPWM) AudioDataDFPWM(pl.asie.charset.lib.audio.types.AudioDataDFPWM) ItemStack(net.minecraft.item.ItemStack)

Example 3 with IDataStorage

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 };
    }
}
Also used : IDataStorage(pl.asie.charset.api.tape.IDataStorage) Callback(li.cil.oc.api.machine.Callback)

Example 4 with IDataStorage

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);
            }
        }
    }
}
Also used : IDataStorage(pl.asie.charset.api.tape.IDataStorage)

Example 5 with IDataStorage

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;
    }
}
Also used : IDataStorage(pl.asie.charset.api.tape.IDataStorage)

Aggregations

IDataStorage (pl.asie.charset.api.tape.IDataStorage)5 Callback (li.cil.oc.api.machine.Callback)1 ItemStack (net.minecraft.item.ItemStack)1 TileEntity (net.minecraft.tileentity.TileEntity)1 EnumFacing (net.minecraft.util.EnumFacing)1 Vec3d (net.minecraft.util.math.Vec3d)1 DFPWM (pl.asie.charset.lib.audio.codec.DFPWM)1 AudioDataDFPWM (pl.asie.charset.lib.audio.types.AudioDataDFPWM)1 AudioSinkBlock (pl.asie.charset.lib.audio.types.AudioSinkBlock)1