/* * Created on 5.3.2007 * * Copyright (c) 2007 Karl Helgason * * http://www.frinika.com * * This file is part of Frinika. * * Frinika is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Frinika is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with Frinika; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.frinika.renderer; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.Arrays; public class CachedRender { File cache; MidiPacketProvider provider; MidiRenderFactory factory; MidiPacketsRenderer render = null; float samplerate; int channels; int rendermode; public CachedRender(File cache, MidiPacketProvider provider, MidiRenderFactory factory, float samplerate, int channels, int rendermode) { this.cache = cache; this.provider = provider; this.factory = factory; this.samplerate = samplerate; this.channels = channels; this.rendermode = rendermode; try { raf = new RandomAccessFile(cache, "rw"); } catch (FileNotFoundException e) { e.printStackTrace(); raf = null; } } RandomAccessFile raf; public void checkFile(int packetsize) { this.packetsize = packetsize; try { boolean fileok = false; if(raf.length() >= 13) { raf.seek(0); byte[] magic = new byte[4]; raf.read(magic); int version = raf.readInt(); boolean bigendian = raf.readBoolean(); int read_packetsize = raf.readInt(); if(new String(magic, "lain1").equals("MRCF")) if(version == 1) if(bigendian == ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN)) if(read_packetsize == packetsize) { fileok = true; } } if(!fileok) { raf.setLength(0); raf.write(new String("MRCF").getBytes("latin1")); raf.writeInt(1); raf.writeBoolean(ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN)); raf.writeInt(packetsize); } } catch(IOException e) { } } int headersize = 4 + 4 + 1 + 4; int packetsize = -1; boolean file_checked = false; byte[] byteBuffer = null; FloatBuffer floatBuffer; boolean dirty_rendered = false; // Random access packet rendering public void getPacket(int index, float[] buffer, int start, int end) { if(!file_checked) { packetsize = (end - start) * 4; packetsize += 1; // Packet Header (status flag), 0=not rendered, 1=rendered, 2=dirty rendered packetsize += 4; // Packet Header (midi checksum), 32 bit long, CRC32 packetsize += 1; // Packet Header (eof flag) checkFile(packetsize); file_checked = false; ByteBuffer bytebuffer = ByteBuffer.allocate((end - start)*4).order(ByteOrder.nativeOrder()); byteBuffer = bytebuffer.array(); floatBuffer = bytebuffer.asFloatBuffer(); } MidiPacket packet = provider.get(index); int packet_chekcsum; if(packet == null) packet_chekcsum = 0; else packet_chekcsum = packet.checksum(); boolean eof_packet = packet == null; long packet_offset = headersize + (((long)packetsize)*index); boolean packetfound = false; if(rendermode != 2) { try { if(raf.length() >= packet_offset+packetsize) { raf.seek(packet_offset); int status = raf.readByte(); int read_checksum = raf.readInt(); boolean eof = raf.readBoolean(); if(!(eof && render != null)) if(status != 0) { packetfound = (read_checksum == packet_chekcsum); } } if(packetfound) { if(render != null) { render.close(); render = null; } if(rendermode == 1) { Arrays.fill(buffer, start, end, 0); return; } System.out.println("read packet : " + packet_chekcsum); raf.read(byteBuffer); floatBuffer.position(0); floatBuffer.get(buffer, start, end); return; } } catch(IOException e) { e.printStackTrace(); packetfound = false; } } if(render == null) { if(eof_packet) // Don't start rendering if curent packet is eof { Arrays.fill(buffer, start, end, 0); return; } render = new MidiPacketsRenderer(factory, samplerate, channels, packet); dirty_rendered = index != 0; } System.out.println("render packet : " + packet_chekcsum); render.render(packet, buffer, start, end); try { if(raf.length() < packet_offset) { raf.seek(raf.length()); while(raf.length() < packet_offset) { if((packet_offset - raf.length()) > 2048) raf.write(emptybuffer); else raf.write(emptybuffer, 0, (int)(packet_offset - raf.length())); } } raf.seek(packet_offset); if(dirty_rendered) raf.writeByte(2); // Dirty rendered else raf.writeByte(1); // rendered raf.writeInt(packet_chekcsum); raf.writeBoolean(eof_packet); floatBuffer.position(0); floatBuffer.put(buffer, start, end); raf.write(byteBuffer); } catch (IOException e) { e.printStackTrace(); } } byte[] emptybuffer = new byte[2048]; { Arrays.fill(emptybuffer, (byte)0); } public void close() { if(render != null) { render.close(); } try { if(raf != null) raf.close(); } catch (IOException e) { e.printStackTrace(); } } }