Need a really simple library for playing sounds and music? Try TinySound.

That is the issue. If you load the whole song into memory uncompressed it is huge. You need to stream it. Titysound streams sound files but not music if I remember correctly. It also supports ogg.

Then there is libgdx which does all of that and then some.

[quote]Memory Usage

The basic loading functions for Music and Sound objects produce implementations
that store all audio data in memory. This is good for maintaining low latency,
but can also require a lot of heap space if you load many, or particularly long,
audio resources. There are loading functions available that allow you to
request that the audio data be streamed from a file. If this is requested, the
audio data will first be converted as usual and then written to a temporary file
from which it will be streamed. This will dramatically reduce the overall
memory usage (after loading), but can potentially introduce occasional latency
when reading from disk.
[/quote]
source: https://github.com/finnkuusisto/TinySound

source: http://finnkuusisto.github.com/TinySound/doc/

Even while streaming it still uses quite a bit of space, but definitely less than without streaming.

Topics merged. Multi posting is dreadful.

public static void startSoundtrack() {
		Thread stThread = new Thread(new Runnable() {

			@Override
			public void run() {
				int currentSong = Main.rng.nextInt(MUSIC_AMOUNT);

				System.out.println("Started soundtrack, now at /music" + currentSong + ".ogg");

				while (!dead) {
					System.out.println("====================");
					
					Sound snd = TinySound.loadSound("music" + currentSong + ".ogg", true);
					if (snd != null)
						snd.play(1);
					
					try {
						Thread.sleep((int) (1000 * 7.2f * 60));
					} catch (InterruptedException e) {
					}

					snd.unload();
					
					currentSong = Main.rng.nextInt(MUSIC_AMOUNT);
					
					System.out.println("Switched song, now at /music" + currentSong + ".ogg");
				}
			}
		});
		
		stThread.start();
	}

This is the latest code, for music only. I switched streaming from file or not (true/false in snd declaration) and the difference was around 3 megabytes. Switching between Sound and Music also makes no difference. It really bothers me when I see VLC using 11 megabytes only while playing them

:-\

Again, sorry I haven’t been on in a while. I’ve been crazy busy with my academic life.

What TinySound does when streaming is it first loads the whole thing into memory to convert to the correct format, writes it to a temporary file, and then streams that. It can thus end up using a lot of memory at loading time, but that should be drastically reduced when streaming. Now, depending on how you monitor memory usage, it can still appear to be using a lot more memory. If you just look at how much memory the JVM has been allocated (e.g. the Task Manager on Windows, or top on Linux), it will be large. This is because it needed that memory at some point. The actual heap space in use when streaming, however, should be much lower. You can tell how much memory is actually in use with something like:


double mbInUse = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1048576.0);

A better solution would be to convert the audio data to the correct format as it’s being read and written out to the temporary file, but I haven’t done that. I don’t think it’s trivial either.

It probably isn’t. After you added the streaming I did what you said kuu and the memory usage is basically 40-50 mb which is fine even thought it says 200+. I still think this lib is great for how easy it is to add sound with ogg support to a game or app.

Well, using mbInUse actually made me see the difference of 160 to 240 but I believe that it’s still stupidly high

That is high. Can you post all of the code you’re testing with?

Edit:
I just took your code that you most recently posted and added the minimum amount required to get it running. I see what you mean about the memory usage, but it appears to be a result of the fact that you load and unload the Sound on each iteration. When I added a

System.gc();

right before the sleep, I was seeing less than 1MB of memory usage at the end of each iteration. The moral of the story is that you shouldn’t load and unload so much. If you’re going to use some music, load it and store it somewhere until you’re done with it. If you’re using the streaming implementation, the Music object itself should take up very little memory, so there’s no reason not to hang onto the reference.

Please let me know if that helps.

During the last years I have tried several solutions for audio in Java games, including the stock JavaSound classes, the JavaZoom libraries, and Paul Lamb’s sound system. But I find the same problem in all of them: under Windows everything works fine, but under Linux (or at least for some distributions/java versions), simultaneous sounds don’t work. You want to play an effect at the same time as music, crash. I have spent many evenings googling about this, but there are contradicting explanations on the internet and to be honest I don’t know a word about pulseaudio, mixers, sound drivers, etc. I’d just like to focus on the gameplay and have the audio work like in Windows :confused:

The only solution I know to work is to use stuff like OpenAL but this requires distributing native code, and I wouldn’t like having different distributions of games depending on the OS.

Is it known whether this library addresses that issue (in pure Java) or it also has that shortcoming? If it does address the issue, I think I’m going to switch to it in no time…

TinySound should work fine on Linux because it mixes all audio to a single line. This was actually one of the problems that I was trying to address when I created TinySound. I did once observe a latency issue with some drivers that I had installed, but others might be able to comment on their experiences.

Any library that does software mixing (like this one) will work fine on Linux. There are a variety of reasons multiple sounds don’t work or don’t work well on Linux when using JavaSound the way Paul Lamb’s system and others do. Even on Windows it’s not a great way to work, constantly getting JavaSound to open and close multiple lines to the soundcard - that’s not how to write any audio software, and just because you can get away with it on Windows don’t assume that’s the way it works cross-platform.

The upside … pick a good library that does mixing in Java and you will get generally get better performance on Linux than Windows. :wink:

Nice lib! I’m gonna have a look-see later.

I’ve been trying to get sound working with various libraries and TinySound seems to be the best for me to use at the moment. It’s been working great but when I profiled my program the memory being used went from it’s usual 10mb and kept increasing over time. After coming to this thread and briefly scanning over a few pages I noticed people saying that the StreamSound/StreamMusic might lower the amount of memory used because the audio files won’t be loaded into memory.

I, for some reason, was unsuccessful in attempting to get StreamMusic/StreamSound to work. Could someone look over the code below and tell me what I should chnage to get it to work.

package Core;

import java.net.URL;
import kuusisto.tinysound.TinySound;
import kuusisto.tinysound.internal.Mixer;
import kuusisto.tinysound.internal.StreamMusic;

public class AudioHandler
{
    
    public AudioHandler()
    {
    }
    
    public void play()
    {
        //initialize TinySound
        TinySound.init();
        //load a sound and music
        //note: you can also load with Files, URLs and InputStreams
        URL url = this.getClass().getClassLoader().getResource("Resources/Sound/MainMenu.mid");
        StreamMusic song;
        Mixer mixer = new Mixer();
        try 
        {
            song = new StreamMusic(url, 100000, mixer);
            song.play(true);
        } 
        catch (Exception e) 
        {
        }
    }
}

I based this off of the one piece of example code I found and then guessed the rest with http://finnkuusisto.github.io/TinySound/doc/ .

TinySound.loadMusic(URL url, boolean streamFromFile)

this first reads the whole audio data from the stream into a temp buffer…
writes the temp buffer to a temp file…
streams from this file…

i’d rearrange the code to something like this


public class AudioHandler
{
    Music music;
    public AudioHandler()
    {
        TinySound.init();
        music = TinySound.loadMusic(...);
    }
    
    public void play()
    {
        music.play(...);
    }
}

when you call play(false) twice, does it play the sound twice?

As far as I can hear, it doesn’t.

@anon951759
I don’t understand. Did you or didn’t you separate the loading from the play as suggested by cubus?

The code that you displayed still has the two together in a single call. Each time you load the file you will burn more memory as you store yet another copy in RAM. That is why the play() method should NOT be in the same method with the loadMusic() method.

Derp… Guess I had the half-updated code in my CnP and didn’t notice. Yes, I separated both of them, here is what the code actually looks like:

private Music music;
    public AudioHandler()
    {
        //initialize TinySound
        TinySound.init();
        //load a sound and music
        //note: you can also load with Files, URLs and InputStreams
        URL url = this.getClass().getClassLoader().getResource("Resources/Sound/MainMenu.mid");
        music = TinySound.loadMusic(url, true);
    }
    
    public void play()
    {
        music.play(false);
    }

It’s still using the same amount of RAM as before the change though. The ‘.mid’ file that I’m using is only 2kb.

Edit: I accidentally left the program open for a few minutes and noticed that it eventually drops back down from 50mb to 25mb so I’ll assume I shouldn’t care too much about the RAM anymore then.

does the memory usage grow, or is it just as before?
that’s what i was pointing out in the first post: TinySound loads the whole audio data and stores it in a temp file, from which it then streams.

i tried the code now. you must call music.rewind() before music.play() to replay it.

the only memory it allocates when replaying is in setPosition() which gets called from rewind(), coz this closes the stream and reopens it. (i don’t know why it is implemented this way, since it creates the temp file, which i thought gets created to have a resetable input stream…???)