New j4k contest anytime soon?

I agree that added inclusion for sound support would be nice, but I also agree with kevglass, I don’t think additional downloads should be necessary. Letting the author deal with any errors, and having sounds playable only on machines with the SDK seems like a fair comprominse, if:

  1. At least one of the judges has the SDK, and can test sound.
  2. Additional points for sounds, or music, are pre-balanced in a good way (and, without knowing the rest of the rules and scoring criteria, I can’t think of any examples on how this should be done).

That way, you CAN add sound, and you CAN get points for it. Yes, it will be expensive, and no, not everyone will be able to play sounds - fine. Provide the download link, let the ones who want to experience the sound do it, but don’t base points on that - base it upon the sole judge, or the judges, that can play it. If judges without SDK can’t, then it should count as not having sound support.

This might be a bad idea, I get those all the time, but it’s what came to mind first. Please note that I haven’t used MIDI sounds at all, so I could very well be missing part of the point.

[quote=“Anon666,post:120,topic:25185”]
But then you could also package the MIDI support as a standard extension, there would be little reason to have the MIDI support in the core.

Midi support can send its data directly to a hardware midi port, resulting generally in the song/sounds played by the soundcard and not the software synth.

So you should be able to get a sequencer and play a midifile without the soundbank.
Unfortunately the method to get the hardware synth is only in the 1.5 API.

It’s been a while since I tested this feature, but I think it’s still valid.

Lilian

Ah, got it.

There’s a few errors in MIDI information provided this this thread. The key points are:

  • The MIDI API is part of the core 1.4.2 API, but the soundbank is an optional part of the JRE install.
  • Even if a soundbank is not fitted, the API supports loading one across the net. Only it’s broken in 1.4.2; Fixed in 1.5.
  • The PC version of the JRE falls back to a hardware MIDI port if a soundbank is not available. Unfortunately this is also partly broken, in that the note timing information is not passed correctly, resulting in the notes being played at the wrong times (sounds like me practicing the piano).
  • I believe you need a 3rd party library (Tritonus) to get MIDI on linux (but looks at kapta’s post - could be wrong)

So, if you get a channel and use noteOn for sound effects, it will probably work on a PC, even with no soundbank. I wouldn’t suggest attempting music though (unless you like that jangley sound). I haven’t checked whether a soundbank is installed on the Mac, so you may or may not get sound.

Alan :slight_smile:

don’t have that 3rd party app, and midi runs fine with linux on java, must be a software midi thing in java on linux.

I tried playing a note with the MidiChannel.noteOn. It works with the sound bank. But if I change the name of the bank so java can’t find it, then no sound is played at all. Unless I am missing something it looks like you need some minimal sound bank to play anything at all.

I checked, and am indeed wrong :-X

It works here. It goes via the windows MIDI Mapper, so perhaps that has been configured to use an external synth.
Have a look here (and the rest of the FAQ for that matter).

The jist of it is that MIDI may or may not work, so you can’t rely on it. My feeling is include it if there’s space, but check for exceptions when initialising, and check for a null pointer before using onNote. Generally using the sampled audio API is a safer bet, but I’ve been unable to get this less than 500 compressed bytes for even the simplest sound, and more than 800 for something decent. I’m managing just under 300 compressed bytes with MIDI at the moment. It’s all a bit academic for me at the moment, as I’ve got two potential entries on the blocks, both of which are having trouble getting into 4k without sound :slight_smile:

Moving away from MIDI for the moment. Part of the overhead with the sampled API is getting a Clip to play just once. loop(0) works the first time, but not subsequently. loop(1) works, but plays the sample twice. In SharpShooter16k I used something like:


                                if (ready) {
                                    ready = false;
                                    fire.setFramePosition(0);
                                    fire.loop(0);
                                }

Originally ‘ready’ was ‘!fire.isRunning()’, but I’ve managed to optimise that out. I’d like to get rid of ‘setFramePosition(0)’, but can’t seem to manage it. Any ideas?.

(I tried loop(1) immediately followed by loop(0), which strangely worked from within the IDE, but not when run by double clicking on the jar. Maybe the IDE was using 1.4.2 & I was getting 1.5.0 when running the jar. Anyway, that whizzo scheme didn’t work)

Alan

Something worth trying - the code to unpack a pack200 stream isn’t that large.

A size reduction may still be possible by embedding the games class file as a pack200 stream, with a little bit of code to unpack the stream, and create a class from it.

I’m still not so sure pack200 is the way to go though - a tool to rearrange the constants pool to improve its compressability will have no code overhead, and should give some gains (it is a simplistic approach to the far more complex techniques employed by the pack200 algorithm)

Are you sure? Unpack200.exe is a stonking 124kB :slight_smile:

I was thinking something along the lines of :-


// btw (not tested in any way, shape or form!)
Class unpack(byte [] pack200data) throws Exception
{
ByteArrayOutputStream  baos;
Pack200.newUnpacker(new ByteArrayInputStream(pack200data), new JarOutputStream(baos = new ByteArrayOutputStream()))
byte [] unpackedData = baos.toByteArray();

final int maxClassSize = SOME_VALUE;
byte [] classData = new byte[maxClassSize];
int classDataLength = new JarInputStream(new ByteArrayInputStream(unpackedData)).read(classData,0,maxClassSize);
return ClassLoader.getSystemClassLoader().defineClass("A", classData, 0, classDataLength);
}

The pack200data would also need to be extracted from a nibble-packed String, as-per jbanes ‘SuperPacker’ (or whatever it was called :D)

p.s.

On a side note, the pack200 api is abit crap - where is the Unpack200[Input/Output]Stream =/

cough 1.4 cough

whaaaat!

1.5 has been out almost an entire year!
I was looking forward to using all the funky new hidden-away 1.5 api bits.
(not to mention forgetting all the hideous work-arounds necessary because of 1.4 bugs/limitations!!)
Infact, what will have changed since last years competition if we use 1.4???

Infact, what will have changed since last years competition if we use 1.4???

The bar is higher :wink:

  1. Pack200 rearranges the class into another format. There’s no stream because the entire class needs to be reconstructed first.
  2. Puttng aside the 1.4 requirement, I think you’ll find that your solution is simply too convoluted to work. In the past we’ve had many a programmer attempt to pack source code into a compressed file, then compile at runtime. As far as I’m aware, all the programmers abandoned their research. I’m not holding out much hope for your scheme, either.

Part of the problem with your scheme (IMHO) is that it involves recompressing compressed data. This is BAD, BAD, BAD as you rarely gain any savings. More often than not, you can actually cause the data to get larger thanks to the fact that the compression algo will be trying to find a way to store so much unique data. The reality of the situation is that you’re better off compressing things once, and optimizing for that.

For example, SuperPackME images compress better than PNGs in a JAR file because they aren’t already compressed. They also shift as much of the unique data to a palette, then present highly redudant data for the compressor to work with.

Which brings me to another point. When coding, try to reuse the same instructions as much as possible. The redundancy caused by those instructions makes it easy for the compressor to shrink the file. Similarly, if you use a method once, don’t be afraid to use it again. Most of the cost is in referencing the class name, then the method signature. Cost-wise, actual use of a method comes in dead last. This means that it sometimes makes more sense to go ahead and use that Math.random() call instead of rewriting your own psuedo-random generator each time you need it.

Good luck! :slight_smile:

I suggested it, as people were claiming the pack200’ed 4k games were being reduced by ~800bytes.

Assuming the overhead of the following 4…

a) the overhead of a second jar head.
b) marginally worse zip compression on the jar, due to the data being nibble-packed.
c) the code to expand the nibble-packed into a byte[]
d) the code to expand the byte [] into a class

…is less than 800 bytes, there should be a saving.

However, I agree pack200 is almost certainly a waste of time - as I don’t think an optimally compressed app. will gain anywhere near 800bytes.

I think a few bytecode optimisation tools will be a much more inteligent application of time, and more likely to give real gains.

hell, may even write it using jasmin =)

Btw, am I the only one who rearanges variables, functions and code in order to get better compression? It’s my favorite part of optemizing for size ;D

Probably, because hardly anyone else know how! So, how do you do that? ???

Na, I thought everyone was doing that! Its the fun bit that helps me learn about how things work underneath. Although, I generally keep trying stuff and comparing sizes and trying to determine patterns :slight_smile:

Kev

yeh that is interesting, how do u, do that?