Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (527)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (594)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2]
  ignore  |  Print  
  Can't figure out how to do Java Audio properly.  (Read 4024 times)
0 Members and 1 Guest are viewing this topic.
Offline DrZoidberg

Senior Devvie


Medals: 17



« Reply #30 - Posted 2013-10-06 00:13:59 »

But now you have an infinite loop that puts 100% load on one CPU core.
That's what the LineListener is for. So you can react to the Clip stopping without needing a loop.
And as I already mentioned you can also use a MouseListener/KeyListener to react to buttons being pressed/released.

Also if you need an isRunning() method in the AudioData class you can define it like this
1  
2  
3  
4  
5  
6  
public synchronized boolean isRunning() {
    for(Clip clip: clipsPlaying) {
        if(clip.isRunning()) return true;
    }
    return false;
}


But I don't think you even need that. AudioData has a stop method. Just call it when the button is released.
Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #31 - Posted 2013-10-06 03:53:29 »

But now you have an infinite loop that puts 100% load on one CPU core.
That's what the LineListener is for. So you can react to the Clip stopping without needing a loop.
And as I already mentioned you can also use a MouseListener/KeyListener to react to buttons being pressed/released.

Also if you need an isRunning() method in the AudioData class you can define it like this
1  
2  
3  
4  
5  
6  
public synchronized boolean isRunning() {
    for(Clip clip: clipsPlaying) {
        if(clip.isRunning()) return true;
    }
    return false;
}


But I don't think you even need that. AudioData has a stop method. Just call it when the button is released.

I don't know how you think you get an infinite loop out of that. It's working fine as it is right now.
Offline DrZoidberg

Senior Devvie


Medals: 17



« Reply #32 - Posted 2013-10-06 05:15:01 »

If you loop a clip this code will run continuously until you set active to false.
1  
2  
3  
while(active) {
    if(!clip.isRunning() && !smoothLoop) active = false;
}

Start a clip with smoothLoop set to true and then look at the Java program in your task manager. One of your CPU cores will have 100% load on it while the clip is playing.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online gouessej
« Reply #33 - Posted 2013-10-06 14:29:19 »

I gave TinySound a look and all I could find was a Github page. I downloaded the ZIP of the project, but I can't figure out how to include it in my project in NetBeans and use the library. What do I do with the ZIP? I've tried including it as a library, adding it to the project, etc... but I can't import anything from the kuusisto package, nor can NetBeans find the TinySound class.
Actually, I don't use TinySound but I assume that you can use its JARs in Netbeans. In the project tab, select the "Libraries" node -> "Add JAR/Folder" and select all JARs.

Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #34 - Posted 2013-10-06 22:17:43 »

Oh, come on! Just when I thought I was in the clear...

Everything works fine when I run the game through NetBeans, but when I Clean & Build it into a JAR and run it, all the sound in the game is cut short... like it only plays half the sound. What could be causing this in the JAR, but not in NetBeans?
Offline philfrei
« Reply #35 - Posted 2013-10-07 02:59:27 »

You may find you will have some fun with computers running Linux, too, if computers running that OS matter to you.

"It's after the end of the world! Don't you know that yet?"
Offline nsigma
« Reply #36 - Posted 2013-10-07 11:23:42 »

Actually, I don't use TinySound but I assume that you can use its JARs in Netbeans.

I was about to respond and say the OP couldn't find the JARs as per my previous message.  Actually, there is a link to them on the GitHub page - assumed it was source only as GitHub deprecated downloads, but they're still there at the moment.

http://finnkuusisto.github.com/TinySound/releases

To the OP, seriously, use a 3rd-party library like various people on here are suggesting.  The way you're using Clip may just about work on some operating systems, but where it does it's not going to perform very well.  Clip is just not designed / implemented in a useful way for this.  You want a system that opens a line to the soundcard and keeps it open, mixing sounds in software - opening a line to the soundcard is not cheap.  And neither are Threads.  Some of the code on or linked to here is woefully inept - a Thread per sound, guys, seriously?!  Emo

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #37 - Posted 2013-10-07 15:13:01 »

I understand what you're saying, but right now, I'd like to know why the sounds are being cut short when I run the JAR as opposed to the NetBeans Run Project button.
I may switch to TinySound after all, but first, I want to know what's causing this.
Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #38 - Posted 2013-10-08 20:03:04 »

Nobody? I really need to know why this is happening.
Offline DrZoidberg

Senior Devvie


Medals: 17



« Reply #39 - Posted 2013-10-08 20:16:46 »

It has probably something to do with threads. Using threads incorrectly can cause all kinds of weird random errors.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline philfrei
« Reply #40 - Posted 2013-10-08 22:03:35 »

A simple case example might help. This isn't a common problem, or at least, it isn't one I've come across before, or heard anyone mention before. Usually if there is a problem that arises in the transition from IDE to jar, it involves the way in which the resources are addressed. But that shouldn't be what is happening in your case since you are able to hear the start of your sounds.

I've found working with sound has tried my patience to the extreme. I don't know that there are many game players that really understand it very well, or even many Java programmers. Most of us are just happy to get something to work.

One exception to this is nsigma. He really knows his stuff, and I recommend paying extra attention to any advice he posts.

"It's after the end of the world! Don't you know that yet?"
Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #41 - Posted 2013-10-09 02:45:08 »

It has probably something to do with threads. Using threads incorrectly can cause all kinds of weird random errors.

Is there a way I could convert it from its current functionality to maybe use a Line Listener like was suggested earlier? I'm not sure if that would correct the problem, but it's worth a try. My code as it is now is:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
public void play(final double gain, final boolean smoothLoop) {
    final Clip clip = createClip();
    FloatControl gainControl = (FloatControl)clip.getControl(FloatControl.Type.MASTER_GAIN);
    float dB = (float)(Math.log(gain) / Math.log(10.0) * 20.0);
    gainControl.setValue(dB);
    new Thread(new Runnable() {
        @Override
        public void run() {
            active = true;
            if(!smoothLoop) clip.start();
            else clip.loop(Clip.LOOP_CONTINUOUSLY);
            while(active) {
                if(!clip.isRunning() && !smoothLoop) active = false;
            }
            if(smoothLoop) clip.stop();
        }
    }).start();
}
Offline philfrei
« Reply #42 - Posted 2013-10-09 18:51:13 »

Here'a an example of the basic form for adding a LineListener, and testing for an event:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
      clip.addLineListener(new LineListener()
      {
         @Override
         public void update(LineEvent arg0)
         {
            if (arg0.getType() == LineEvent.Type.STOP)
            {  
               // do something}
            }
         }
      });


But that begs the question of how a looping clip gets a signal to stop in the first place.

If we are talking about a machine gun with a fixed duration, e.g. short bursts, something like this is fine. (No LineListener needed. No while loop needed.)

1  
2  
3  
   clip.start();  // assume looping, volume, etc. has already been set up.
   Thread.sleep(machineGunDuration);
   clip.stop();  // then maybe reset it to the starting frame so you can reuse it


Sometimes I break the Thread.sleep() into smaller increments and check a state variable before continuing to the next sleep, to make the duration more granular. The state variable should be volatile, of course, and will only be as accurate as the limited real time guarantees of the JVM/OS.

1  
2  
3  
4  
5  
6  
7  
   clip.start();
   for (int i = 0; i = 10; i++)
   {
      Thread.sleep(oneTenthMachineGunDuration);
      if (stopClip) break;
   }
   clip.stop();


Am just free-typing this. So, hopefully I didn't facepalm anything.

Even the 2nd example above uses vastly less cpu than leaving the thread spinning. I've only seen spinning threads in "spin locks" where the anticipated duration was very short.

Couple of suggestions/observations which may help in other regards:

 - It is kind of unusual to make a new Clip and play it with every play. Usually one restarts a given clip. If you are doing a single playback, a SourceDataLine starts quicker, so as not to incur the repeated i/o loading. Maybe you are doing this as a quick/dirty way to allow concurrent sounds?
 
 - Not every OS will support MASTER_GAIN, just a heads up.

 - Not every OS will support multiple outputs (for sure some Linux won't), hence the recommendation for TinySound which mixes all sounds into a single output line. Of course, to get TinySound, we are back at the annoying task of figuring out how to use GitHub. But since Git is such a common tool for sharing code, the "side trip" is worth it, imho.

"It's after the end of the world! Don't you know that yet?"
Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #43 - Posted 2013-10-10 02:28:54 »

Here'a an example of the basic form for adding a LineListener, and testing for an event:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
      clip.addLineListener(new LineListener()
      {
         @Override
         public void update(LineEvent arg0)
         {
            if (arg0.getType() == LineEvent.Type.STOP)
            {  
               // do something}
            }
         }
      });


But that begs the question of how a looping clip gets a signal to stop in the first place.

If we are talking about a machine gun with a fixed duration, e.g. short bursts, something like this is fine. (No LineListener needed. No while loop needed.)

1  
2  
3  
   clip.start();  // assume looping, volume, etc. has already been set up.
   Thread.sleep(machineGunDuration);
   clip.stop();  // then maybe reset it to the starting frame so you can reuse it


Sometimes I break the Thread.sleep() into smaller increments and check a state variable before continuing to the next sleep, to make the duration more granular. The state variable should be volatile, of course, and will only be as accurate as the limited real time guarantees of the JVM/OS.

1  
2  
3  
4  
5  
6  
7  
   clip.start();
   for (int i = 0; i = 10; i++)
   {
      Thread.sleep(oneTenthMachineGunDuration);
      if (stopClip) break;
   }
   clip.stop();


Am just free-typing this. So, hopefully I didn't facepalm anything.

Even the 2nd example above uses vastly less cpu than leaving the thread spinning. I've only seen spinning threads in "spin locks" where the anticipated duration was very short.

Couple of suggestions/observations which may help in other regards:

 - It is kind of unusual to make a new Clip and play it with every play. Usually one restarts a given clip. If you are doing a single playback, a SourceDataLine starts quicker, so as not to incur the repeated i/o loading. Maybe you are doing this as a quick/dirty way to allow concurrent sounds?
 
 - Not every OS will support MASTER_GAIN, just a heads up.

 - Not every OS will support multiple outputs (for sure some Linux won't), hence the recommendation for TinySound which mixes all sounds into a single output line. Of course, to get TinySound, we are back at the annoying task of figuring out how to use GitHub. But since Git is such a common tool for sharing code, the "side trip" is worth it, imho.

Ok, can I just ask how the idea got started that I was talking about the machine gun? The machine gun is not looped, and the sound is played every time the gun is fired... the flamethrower is what's looped. That being said, it doesn't seem like anyone has a solution for this, so I'm gonna try my hand at TinySound.
Offline philfrei
« Reply #44 - Posted 2013-10-10 02:41:06 »

I once used a loop for a machine gun sound effect built from individual gunshots. From that I made a mental error.

Substitute the words flamethrower for machine gun. The above should still work.

"It's after the end of the world! Don't you know that yet?"
Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #45 - Posted 2013-10-10 05:57:57 »

I once used a loop for a machine gun sound effect built from individual gunshots. From that I made a mental error.

Substitute the words flamethrower for machine gun. The above should still work.

That's the problem, though. What you posted is exactly what I was doing originally that caused the overlapping sounds to freeze the game.
Offline philfrei
« Reply #46 - Posted 2013-10-10 09:30:17 »

Mmmm. I'm having trouble keeping track. The overlapping sounds are freezing the game? That makes me wonder about deadlocks. Your early code had a lot of synchronization. Are you still employing that? Infinite loops also come to mind as a plausible cause.

An earlier post said that the sounds would play but only half-way ("cut short"), and I didn't see mention of the game freezing with that post. So I assumed that the game continued and only the sounds were acting weird. I have no idea what would cause that, except maybe attempting to use a given clip concurrently (where the second play causes the cut-off).

I had another thought about managing the flamethrower, if you are still entertaining various strategies for handling that. I am working from the assumption that the sound is a looping clip. The "problem" then is how to have the event which stops the flamethrower find this clip in order to issue a clip.stop(). Yes? I'm going to assume that there may be more than one flamethrower operating at a given time, but that we can identify the operator of the flamethrower when we start or stop it.

One thing I started doing is to create a single class called GameSound, and have it handle all the sound f/x. Within that class, I'd have a public method like .flameThrower(operator, flaming). Then have this method do the following:

if flaming is true, get an instance of the clip (from a preallocated pool), store it with the operator in a hash table, and start the clip.

if flaming is false, use the operator to locate the clip in the hash table, and stop the clip, resetting it to starting position and returning it to the pool.

I've been using the pooling idea for a 'SoundField' tool (used to randomly play a selection of sounds, with overlapping of same sounds supported) and also for various synths that are polyphonic (creating a pool of "notes"), and it has worked without needing synchronization to manage the pool. It took a little head-scratching to keep it concurrency safe, but it was doable.

What is kind of vexing for many is that these sorts of things aren't available directly from Java or from most game libraries even though they seem like they should be common. Java sound gets pretty low level, and the high level capabilities they do provide are a take-em-or-leave-em proposition.

"It's after the end of the world! Don't you know that yet?"
Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #47 - Posted 2013-10-10 13:21:35 »

Phil, please read earlier in the thread. I already said I corrected the freezing issue... the sounds being cut short is unrelated. And just a few posts up is the code I'm currently using.
Offline packetpirate

Junior Devvie


Medals: 1
Projects: 1



« Reply #48 - Posted 2013-10-10 17:02:24 »

Alright, so I switched over to TinySound and got it working for the weapons. But there's one remaining problem. I went with the Music object, rather than Sound, so I could make the Flamethrower work (needed to be able to loop it and only play it if it's not already playing). The problem being that now the zombie moans are doing exactly what I originally set out to fix, being that I need them to overlap, and the Music object seems to restart the sound whenever the play() is called, which I understand... but how can I support playing the same sound over itself like I was doing with the AudioData class I made?

EDIT: Nevermind. I just decided to go with loading the sound every time it's played if it's designated as an overlapping sound (really only used for the moans) and playing that instead. Otherwise, it just uses the sound it loaded at the start. I realize this may not be very efficient, but I'm going to be making it so zombies only moan once after they're spawned so it doesn't cause too much of a burden.


Why is sound so troublesome in Java?
Offline zngga
« Reply #49 - Posted 2013-10-10 17:47:00 »

I think sound is troublesome in every language... just other languages hide it better.

My code never has bugs... it just develops unexpected features!
Pages: 1 [2]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

PocketCrafter7 (14 views)
2014-11-28 16:25:35

PocketCrafter7 (9 views)
2014-11-28 16:25:09

PocketCrafter7 (10 views)
2014-11-28 16:24:29

toopeicgaming1999 (76 views)
2014-11-26 15:22:04

toopeicgaming1999 (66 views)
2014-11-26 15:20:36

toopeicgaming1999 (15 views)
2014-11-26 15:20:08

SHC (30 views)
2014-11-25 12:00:59

SHC (28 views)
2014-11-25 11:53:45

Norakomi (32 views)
2014-11-25 11:26:43

Gibbo3771 (28 views)
2014-11-24 19:59:16
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!