Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (731)
Games in Android Showcase (217)
games submitted by our members
Games in WIP (799)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
   Home   Help   Search   Login   Register   
  Show Posts
Pages: [1] 2 3 ... 51
1  Discussions / Business and Project Management Discussions / Re: Licensing overwhelm, asking for advice on: 2017-06-27 21:19:40
Thanks for the really interesting links and discussion, @Catharsis!

It has me on the fence again, though. The suggestion of putting a more restrictive license (after making the initial version BSD-type) on a later version is plausible. I am seriously wanting to add cross-fading to loop ends when looping, as well as a random-macro-granule-streaming option. This could be the higher value version.

Here is a thought: Suppose I just retain the copyright for now, but let folks on Java-Gaming.org know that I will grant permission to members to try it out and to use it on a given game. All they have to do is ask me, via PM.

Maybe this is a little overly cautious or control-freaky. But this would perhaps let us know if the code is even worth worrying about, if there is even a problem it solves that matters to Java game makers. (For anyone using LWJGL-derived or JOGL, it won't be relevant.)

I will make some effort today towards getting a jar posted that can be tried out, and will post it on the Audio thread when I have it set up.
2  Discussions / Business and Project Management Discussions / Re: Licensing overwhelm, asking for advice on: 2017-06-26 15:04:07
Having three solid endorsements--takes a big load off of my mind.
Thanks!
3  Discussions / Business and Project Management Discussions / Re: Licensing overwhelm, asking for advice on: 2017-06-26 06:03:29
Interesting option. I was kind of shocked to see the following listed as one of the three clauses in the BSD-3-Clause

Quote
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

Do people do that sort of thing?
Is it legal to do that? I mean, maybe the clause isn't needed if it is illegal for someone to say you endorse something without your permission.
Jeez.

The main thing I'm hoping is that some game programmers find the code useful, using it as a kind of souped-up Clip class. But I'd like some credit as the developer and certainly don't want to find myself in any sort of situation where I am prevented from using my own code.
4  Discussions / Business and Project Management Discussions / Licensing overwhelm, asking for advice on: 2017-06-26 05:25:21
I'm just about ready to post a class, AudioCue, but am really confused about all the complexities around copyright and licenses.

Started by looking at LGPL ("Lesser Gnu Public License") but their documentation suggests the relatively small amount code might be better served by Apache 2.0 license. So, I was looking at that and trying to figure it all out.

Then, took a look at the MIT license. It is short and simple, and would suffice. The main thing I'm wondering is if it would be okay or reasonable to add a clause that requires including the Project Name and/or a URL where I plan to maintain a copy of the source code as well as a record of revisions as I make them.

Have others done this? Examples of the wording?
Parts in BLUE I added.

OK, here is a possible draft:

Quote
This file is part of the AudioCue project
Copyright 2017 Philip Freihofner

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The version number supplied with the @version tag in the Javacoc class-level comment, will be retained, and, if modifications have been made, the words "with modifications" will be appended to the @version tag and an additional JavaDoc @author tag or tags will be included crediting the authorship of the modifications.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


I'm now thinking, maybe there is no need to mention that there is a url with source. Someone could probably find their way there via my name and the project name and searching.
5  Discussions / General Discussions / Re: Programmer jokes on: 2017-06-26 05:16:10
Not jokes, but programmer-related humor (loosely defined).

Caption in search of a cartoon:

The Hunchback of Code Domains

(Has it been used before? Or something similar? Feeling somewhat Quasimodo-like after hunching over keyboard for long hours.)

Also, had an idea for a game, inspired by my wife, called "Die Fly! Die!"

Avatar runs around apartment interior armed with either swatter, rolled up newspaper, shoe, trying to kill fly or flies that came in when letting the cat out. Points for flies killed (time-based), negative points for furniture destroyed, walls marred, etc.
6  Java Game APIs & Engines / Java Sound & OpenAL / Re: Multiple clips on the same line on: 2017-06-23 16:59:14
Finished a draft of the API. Am working on html page for posting, and figuring out license (worst case scenario: requirement to post a single link on an "About" page or "Credits" page).

TinySound is a good library! Glad you gave it a try.

AudioCue will have some advantages and disadvantages. It doesn't mix everything together into a single output line (advantage TinySound) but I can't recall if TinySound has real time volume, panning and frequency changes, or if it lets you position the "playhead" to different points. I probably should have looked closely at its API before designing mine, though. I think AudioCue will be similarly easy to use (or at least in the ballpark).

All right, I actually have a hour to work on it this morning--better stop procrastinating.
7  Game Development / Newbie & Debugging Questions / Re: I.T. professional: bored of being a tool - "Please Advise" on: 2017-06-21 22:31:02

You've said that you're still a novice programmer, and that's completely okay! But that also means that most of the code you write right now is going to look like crap to you in 6 months- that's a sign of you growing, and it happens to all of us. But the point is that there really isn't a point in starting out creating an engine, since you'd probably end up rewriting anything you did right now anyway.


I don't know about this advice. It seems to me, if you don't take the time to write what turns out to be "crap" code, how do you grow?

Coding is a lot like a muscle--you have to engage in the problem solving activities in order to improve your ability to problem solve.

If you are just going to "template code" (and avoid any heavy lifting), might as well just use a builder tool and forego coding. Rewrites are both an inevitable and necessary part of learning. Hard to truly understand how important something is until you try and discover why the 'obvious' solution doesn't always work.

If game-engines are a passion, why not? There is a lot to be learned there. I'm not saying it is any better or worse a career path than making games, though.
8  Game Development / Shared Code / Re: "Better" LinkedList implementation on: 2017-06-18 19:41:01
Nice!
Are you thinking about a concurrency-safe version by chance, or is that definitely not an issue in your situation?

Multi-threading is on my mind as I just used a LinkedBlockingDeque for safely managing concurrent calls to an AudioCue class that allows concurrent playback. Am only using offerFirst and pollLast methods. Only a handful of instances per Cue play at one time, so efficiency is less of a concern than reliability.
9  Game Development / Newbie & Debugging Questions / Re: I.T. professional: bored of being a tool - "Please Advise" on: 2017-06-18 01:42:29
Sounds to me like you are itching to learn more. Some people have a game idea that they want to bring to life, and not so worried about gaining programming skills. It makes sense that they would not wish to "waste" a lot of time learning coding to any great depth.

I've been amazed at what can be done with the "Blueprints" stuff that comes with Unreal. The tool set is incredible. I assume the same is true for Unity. I could see making all sorts of games within the bounds of what they have made available.

Completing a game and marketing it is a considerable accomplishment. But it is going to help more with design work and showing you can see something through to the end than it will show programming skills.

I really don't know what to advise, beyond checking out Gamasutra, perhaps, for the job listings that are current, and deciding if some of them are worth targeting when you decide what to study or do next.

I decided to go my own way with audio coding, and have learned a lot, about both audio and Java. I had some notions that by getting off the beaten path and building something myself, from scratch, I would learn interesting things and gain perspectives that were different from people who follow the main roads. Part of where coming from: working with gear as a composer (e.g., Yamaha DX-7 or the Native Instruments FM-7/FM-8, or various DAW's) and being annoyed that I couldn't experiment with ideas unless the capabilities were implemented. Didn't like the notion of my creative ideas being constrained by decisions made by engineers. Wanted, therefore, to make my own tools. Unclear yet whether it will lead to a job in the industry. I'm not exactly regretting the choice, but feel like I have a long ways to go yet to earn income from game coding. But part of that could just be the near impossibility of competing in an industry flooded with content.
10  Games Center / Cube World Projects / Re: [JOML] How to get multiple octaves of SimplexNoise? on: 2017-06-15 16:14:07
Is there a particular pattern you are going for?

With the more complex patterns, you have to make multiple calls to the simplex function for each pixel and combine them. Usually this is done with addition, where each octave is given its own weight. It is not necessary to do so, but usually folks scale the multiple calls via some sort of fractal relationship. For example, a nice cloud pattern can be had that way.

Pseudo code:
1  
2  
3  
4  
5  
    noiseValue = simplex(x, y) / 2;
    noiseValue += simplex(x * 2, y * 2) / 4;
    noiseValue += simplex(x * 4, y * 4) / 8;
    noiseValue += simplex(x * 8, y * 8) / 16;
    etc.

The results will range in between -1 and 1. You can then scale that to color values in various ways. Applying an ABS function to the result before scaling is an option that Ken Perlin called "turbulent" as opposed to "smooth".

Most importantly, for terrain, instead of scaling the noiseValue to a gradient of a color (as in Red in the range 0..255 or 0..1 depending on what command you are using), one uses a color mapping. I first read about this in a blog post by a jgo member @ShannonSmith
http://www.angryoctopus.co.nz/?p=11

We have a pretty good article here: http://www.java-gaming.org/topics/noise-bandpassed-white/27071/view.html

I made a 'visualizer' to help with playing around with different ratios and scalings using a GUI. It uses Gustafson's implementation of 2D simplex, but if you were to swap in another simplex function, the results should be similar. There is a link to a jar and the github site on this thread:
http://www.java-gaming.org/topics/sivi-2d-simplex-noise-visualizer-tool/30187/view.html
The html implementation link to the visualizer is obsolete.

As part of the visualizer tool, there is a 'gallery' of graphics that can be loaded and fiddled with. The input scalings are apparent (each channel column has fields where values are plugged in), but the "mixer" could be clearer in terms of letting you figure out what numbers to use to scale each output to get the visualized effect.

If I remember correctly, what is going on is this: the values shown on each octave slider are numerators and the sum of all the channels is the denominator. So, if one channel reads 24 and another reads 48, the ratio will be 24/72 and 48/72. There is also a total volume slider (bottom most) which scales everything equally. The display uses values that range 0..255, so if the highest value is 72, output to the graphic is on the low side. If the bottom slider is pushed to the right, it scales everything up by the same factor and can overflow beyond 255 (or be clamped at 255).
11  Game Development / Newbie & Debugging Questions / Re: Why AnimationTimer and setTranslate on a ImageView node create jerky movement? on: 2017-06-14 05:04:23
Thanks for letting us know the resolution.
12  Java Game APIs & Engines / Java Sound & OpenAL / Re: Multiple clips on the same line on: 2017-06-14 02:15:04
Neat idea, to place several audio clips on the same audio file! I hadn't thought of doing that. How do you stop the cue at the right place? Are you counting frames somehow?

To collect all sounds and send them out a single line, you have to write a mixing algorithm yourself or make use of a library such as TinySound which does exactly this. (By mixer I mean the equivalent of an audio mixer as studio gear, not the javax.sound.sampled.Mixer class which is something different.)

To mix, it is matter of getting at the individual PCM sound frames (can be done by first loading the cues into memory arrays or using an AudioinputStream if you are playing back from a file), and summing them, then outputting the sum on a SourceDataLine.

I have been working pretty hard, actually, on a class I'm calling an AudioCue. There is a weak first pass already posted here at JGO. It will allow concurrent sound effects for any sound effect line that is "opened", where all the concurrent plays will be summed into a single output for that cue. (Example: variable number of bullets in quick succession for simulating a semi-automatic rifle, all come from one cue and all output on single line, despite the cues being played in a concurrent, overlapping fashion.) The new version I am about to post has reliable and smooth volume, pan, and frequency faders, so the same sound can be played back at different speeds at the same time and still be counted as a single output line.

I could just go ahead and post it now if it would be useful, or send you a preview, but I am still working on the JavaDocs for it and want to rewrite the panning into a lambda form, so different types of panning could be used. Also want to put in some input argument safety checks and clamping on the output. It is easy to overdrive and create wretched noises if you aren't careful. (But not so bad if you know what you are doing and understand audio.)

This class would allow you to do:
1) load all your 30--40 different sounds into memory
2) easily open and shut the lines as needed (assuming different segments of the game use different sounds).

If some of the sounds can do double duty by varying the speed or if some of your 30-40 are implementations of concurrent uses of clips, this could get you a long way towards reducing the number of lines that need to be open at once.

I haven't timed the lag for the combo open/play with this class yet as I hadn't anticipated that use. But if you can run an open method a good 100 millis prior to play as a preparatory step, that would easily be a good safety margin.  

Anyway, you probably just need to go to a library.
How far along is your game, otherwise?
Is it possible to check out what you have so far?
I do have a mixer library I wrote that does the mixing I described--maybe I can rig up a version that will handle your needs.
13  Game Development / Newbie & Debugging Questions / Re: Why AnimationTimer and setTranslate on a ImageView node create jerky movement? on: 2017-06-13 17:51:00
For responsive controls, what I recommend is to have asynchronous input (keyboard and mouse) be used to set volatile variables. Then, in the AnimationTimer (the game loop), consume those values and update the animations accordingly. This is working pretty well so far on the 2D game JavaFX game I work on intermittently.
14  Game Development / Newbie & Debugging Questions / Re: Why AnimationTimer and setTranslate on a ImageView node create jerky movement? on: 2017-06-13 17:40:53
In my limited experience, AnimationTimer does a pretty good job of maintaining 60fps. When I ran the code, it looked fine. I'm not clear what the problem is.

If the scan rate on the monitor is something more different from 60, like 75 say, maybe that would help? I couldn't test this because I can't find where Windows10 let's one set the monitor refresh rate.

You might find it interesting to store the highest and lowest deviations. Store the last "now" long and compare it to the current "now" argument from the handle method. Or to tally the range of timing differences that occur.

Here is a short JavaFX graphics test program I wrote that is similar to your code (object bouncing side to side), though I am not using an ImageView in this case. Use of ImageView shouldn't make a difference. As far as I know this animation is reasonably smooth. Does it work for your setup?

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class BasicGraphicsDemo2 extends Application{

   final int WIDTH = 600;
   final int HEIGHT = 400;
   
   double ballRadius = 40;
   double ballX = 100;
   double ballY = 200;  
   double xSpeed = 4;
   
   public static void main(String[] args) {
     
      launch(args);
   }
   
   @Override
   public void start(Stage stage) throws Exception {
   
      stage.setTitle("Basic JavaFX demo");
     
      Group root = new Group();
      Scene scene = new Scene(root, WIDTH, HEIGHT);
     
      Circle circle = new Circle();
   
      circle.setCenterX(ballX);
      circle.setCenterY(ballY);
      circle.setRadius(ballRadius);
      circle.setFill(Color.BLUE);
      root.getChildren().add(circle);
     
      stage.setScene(scene);      
      stage.show();

      AnimationTimer animator = new AnimationTimer()
      {
         @Override
         public void handle(long arg0)
         {
            ballX += xSpeed;
           
            if (ballX + ballRadius >= WIDTH)
            {
               ballX = WIDTH - ballRadius;
               xSpeed *= -1;
            } else if (ballX - ballRadius < 0) {
               ballX = 0 + ballRadius;
               xSpeed *= -1;
            }
   
            circle.setCenterX(ballX);
         }  
      };

      animator.start();

   }
}



15  Game Development / Newbie & Debugging Questions / Re: How do I iterate through a list that is modified outside of the current loop? on: 2017-06-07 22:19:45
CopyOnWriteArray is used very much like an ArrayList. So yes, the declaration you wrote looks good.

CopyOnWriteArray is concurrency safe, so you can add to it or delete from it from another thread, even during an iteration. What happens is basically this: the new item (or lack of item) becomes part of the next iteration when a new "snapshot" of the list is taken.

CopyOnWriteArray works best in situations where iterations greatly outnumber adds and deletes to the list, assuming nothing will break when the "snapshot" list runs to completion.  If that doesn't describe your situation, maybe we can help come up with some alternate plans.
16  Discussions / Miscellaneous Topics / Re: What I did today on: 2017-06-06 03:17:43
@Damocles - Really nice looking! Can I assume you will add more variation, in the future, to the debris source particles rather than reusing graphics as much as you do in this iteration?

Today I was at work at the music store, so did very little programming. (Not true, exactly. I found a book at "Half Price" two weeks ago about Java Sound programming! It has a lot of obsolete code in it: the author had to make his own GUI from scratch because he was coding before Swing! But the basic audio processing algorithms for different effects are still very useful and can be rewritten. Will be going from Java 1.1 to 1.8! Was reading about his compressor/limiter unit today on my break.)

As I was saying, did little programming, but my tutorial on Beginning JavaFX Game programming, posted here at JGO about 15 months ago, today it passed the 100K hits mark! So "whoo-hoo!" for that. I hope the relatively high total means people are coming back and referencing it, not just checking it out and deciding it is bunk and never coming back. I don't know if JGO has metrics for that sort of thing.

Tired. Long day. Will be back to Java coding tomorrow, as well as working through Unreal "Blueprint" tutorials for part of the day.
17  Discussions / Miscellaneous Topics / Re: What I did today on: 2017-06-03 08:21:10
Nice to spend the day programming Java.

Things actually done in last 24:
> some fixes and changes to the noise-sculpting experiments I posted in WIP,
> tackled and solved a concurrency problem in the AudioCue design pertaining to allowing multiple instances of a Clip to be played at the same time.

For the latter, this included building a tester to bombarded an AudioCue with play() requests from multiple threads. I was able to prove that I had indeed set up a race condition, but also figured out, and able do demonstrate to myself with this test framework that I could use a concurrent, fixed-length "FIFO" [LinkedBlockingDeque, with pollLast() and offerFirst(Note)] to manage the "available instances" while retaining a simple array of instances for the while loop where the instances get mixed to a single output stream.
18  Games Center / WIP games, tools & toy projects / Re: noise sculpting experiments on: 2017-06-03 08:03:25
The Rumble definitely causes distortion pops if you have the slider over 70. They occur more frequently the higher you push it.

I probably should have put in min/max to stop this or not allowed the volume to go up beyond the point were intermittent pops were happening.

This makes me think, also, that maybe a way to get more volume from noise at low random frequencies is to use compression of some sort. I will have to play around with this.

Yes, it is kind of counter-intuitive that rain/thunder would be relaxing. I also find this to be true, with one notable exception: storm is so intense/close that the building is shaking (from either the wind or from nearby lightning).

Thanks for the links! Pretty cool.
19  Games Center / WIP games, tools & toy projects / noise sculpting experiments on: 2017-06-02 22:28:03

dunewind.jar
audio sample of three effects mixed together/all playing at once.

This is more experimental than work towards a given application or game.

I have been playing around with some noise sculpting via Java and thought I'd share the jar. Objectivity comes and goes, and I sometimes get into states where I can't tell if something is intereting or a waste of time. So it would be nice to hear what others think. Among other things, I have found that it is really easy for me to hear what I think I programmed instead of hearing what is really being produced.

The noise sources in each case originated with 10-second "generated content" files from Audacity. Pretty cool that you can pick a type of noise (e.g., White, Pink, Brownian) and have it create a track for you.

In each of these, I am using a tool that plays back a continuous string of "macro-granules", basically jumping into random places in the file and contatenating short fragments of the audio content with a bit of overlap to smooth the joins.

The tool was rebuilt so that each stereo channel could have its volume modulated independently. Also, a control was put in to allow variable playback speeds but it is not channel independent.

The rumble started with Brownian noise, filtered with 6 db rolloff at 75Hz, both low-pass and high-pass. It seems to break up (distort) with increasing likelihood as one pushes the volume above 70. I'm wondering how film theaters get that amazing rumble. Can't seem to do it with headphones without cranking the volume of the external amplifier and turning all the other sounds way down in volume. Maybe theaters just have really strong sub-woofers hooked up. I have been experimenting with various filter settings of white and pink noise as well as Brownian, and have not found an "ultimate rumble".

The "wind-in-ears" also uses Brownian noise, but in this case filtered high-pass at 400Hz and low-pass at 600Hz, 12 db rolloffs. I was playing around with some randomized lfo to create "gusts". I was hoping to get a sense of direction by varying the time between when the turbulence altered the left and right ear sound sources. The first person offering feedback said it was too subtle for him to hear directionality. I did some bug-fixing and modifications and the setting on the graphic seems to sound pretty good. Try moving the "ear-to-ear" difference from around -15 to 15 and back, with turbulence well over 50, and the other components silent, if the ear-to-ear sense is not audible. I meant for the left-side of the slider to correspond to the head turning left and the wind hitting the right ear first (and vice versa for the other direction). Closing the eyes seems to help. Thoughts on whether or not this works as a possible VR effect?

The "sand" swirling all around is also kind of problematic. I altered the control that is providing "turbulence" to rise much more quickly than it drops (am imagining some sort of craft riding through sand dunes as if they were waves). With each bump, the playback rate drops (making the sound a little more thud-like) then speeds up (making the sound dissipate in a more hiss-like state). I made two of these sand-generating sliders to add to the surround-sound nature. I'm still pondering how to incorporate changes to convey directionality when one turns one's head.

All in all, still playing around and experimenting with how these noises can be altered in realtime and make useful effects. Am trying to expose useful controls to help search and discover useful settings. I've spent so much time coding that I've kind of lost touch with sound design, so it is nice to exercise that muscle again and try and figure out how to cook up some decent noise-based effects.
20  Discussions / Miscellaneous Topics / Re: What I did today on: 2017-06-02 21:34:26
Attended the Augmented World Expo (AWE) yesterday, helping out exhibitor Rogue Reality. Got to play some fun VR games in the process: TitanSlayer and QuiVr. Saw a bunch of neat exhibits, but mostly hung out with the RogueReality group. Meeting and talking to people (setting them up to play the games) was pretty fun.

Rogue Reality rents out VR gear for parties and events. They are dabbling with asset development for VR which is how I got interested/involved. They are the main reason why I'm studying Unreal and C++ at the moment.
21  Games Center / Showcase / Re: [LibGDX] Nano Nox - Now on Steam Greenlight on: 2017-05-29 15:38:38
Cool visual design.

Is the music heard part of the game? Given the translucent images and particles, and the lightning effects, I think music could be found that was a somewhat better match. It is well written, well produced, I'll give it that. (Maybe just a matter of personal taste--can't please everybody!)
22  Discussions / Miscellaneous Topics / Re: What I did today on: 2017-05-26 05:57:38
Been busy with various work testing possible audio VR algorithms. I've been writing mockups in Java for things like a vR wind-in-ears. The goal is to include some enhanced audio features in an Unreal project. I'll talk more about them when things are further along. I'd like to make them available to the Java game-making community, too. In any event, I figure it makes sense to first hear if these ideas work or not before trying to write them in C++, a language I with which I do not have much experienced.

(On my brother's advice, am reading Stroustrup's book. I figure if anyone can make rhyme or reason about some of the complexity of C++, it should be the author of the program!)

Today, though, was spent on the AudioClip class that I started in the 'shared code' section a couple weeks ago. The goal is to have an open-source, "improved" Clip for people not ready to make the jump to an audio library. I made a lot of progress today! Got the position-setting features of Clip working, and also put in place code for variable speed playback. Also, wrote test cases for the varispeed playback and position resetting. Put in place a looping capability that I didn't test yet, and the ability to smoothly fade-in and fade-out with the volume as well as alter the playback speed while a cue is playing. The concurrent playback aspect was implemented in the original post.

I'm going to write more test cases to ensure I have all the features working, and maybe a demo (slider for volume, slider for playback speed) before I post the updated code here at JGO. Hope to get to this before the end of the month or within a few days of that.
23  Java Game APIs & Engines / Java Sound & OpenAL / Re: Sound tool recommendations and/or javax.sound problems on: 2017-05-16 02:57:23
@Optimo -- I started work on a Clip that allows concurrent playback. You can download it from the SharedCode area.

I think the next step will be providing a way to do normal Clip things like position the cursor and loop. Then I'll get a real-time volume control working based on one I've used before. It spreads the volume change out over 1024 frames which is quick enough for most perceptions where fading is occurring and small enough increments to prevent zippering. Will try to find time to do this before end of May.
24  Game Development / Shared Code / AudioCue, starting point for concurrent Clip on: 2017-05-08 07:00:26
Jar file, with source and three audio samples can be downloaded from audiocue.jar.

The goal of the class AudioCue is to make a control that is relatively easy to use and has capabilities not available with the Java Clip (javax.audio.sampled.Clip).

This is just a starting point. There is a LOT that you can do with a Clip that I haven't implemented yet. The only thing I put in was the ability to set the volume of the play(), and to allow AudioCue to play concurrently. But the framework is there for additional features to be added on, such as looping, or playing back at various speeds, or altering the volume during playback. I'll try to find the time to add these capabilities in the next few weeks, but probably won't be able to do much until at least June.

My strategy for concurrent play back is to have all instances of the cue mixed together and output via a single javax.audio.sampled.SourceDataLine. It is possible to rig up multiple Java Clips of the same cue, to allow the sound to be played over itself, but each Clip opens up a new line for audio output. I thought it a good idea to keep all the occurrences grouped in the same output line. NOTE: if you are using audio files that were recorded at loudest possible volume, you will have to back off on the volume for concurrent playback to avoid distortion.

Some code reading/review would be great! I'm open to others tinkering and proposing changes or using the code and making their own changes.

The code has some diagnostics in it that can be observed if run from the console. You'll probably want to comment them out if you use this code yourself.

The "test" class file will first play a normal Java Clip, then three overlapping plays of the AudioCue. The pauses are on the long side, to accommodate the longest of the three audio samples that I included. The included samples are a gunshot, a bell, and a frog croak. You can use comments on the code to select which sound you wish to test.

This first file is the code for testing the class.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
package jgo;

import java.io.IOException;
import java.net.URL;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class TestAudioCue {

   public static void main(String[] args) throws LineUnavailableException,
      UnsupportedAudioFileException, IOException, InterruptedException
   {
      System.out.println("TestAudioCue() start");
      TestAudioCue test = new TestAudioCue();
      URL url;
      url = test.getClass().getResource("GunshotIndoor3.wav");
//      url = test.getClass().getResource("a3.wav");
//      url = test.getClass().getResource("frog.wav");
     
      System.out.println("Test Normal Java Clip");
       AudioInputStream ais = AudioSystem.getAudioInputStream(url);
       DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
       Clip clip = (Clip) AudioSystem.getLine(info);
       clip.open(ais);
       
      Thread.sleep(100);
       // The "play" of the normal Java Clip
      clip.start();
       Thread.sleep(8000);
       clip.close();
       
       System.out.println("Test new AudioCue");
      AudioCue cue = new AudioCue(url);
      cue.open();
      Thread.sleep(100);
         
      cue.play(0.8f);  // range of volume is a float, 0 to 1
      Thread.sleep(750);
      cue.play(0.8f);
      Thread.sleep(250);
      cue.play(0.8f);
     
      Thread.sleep(8000);
      cue.close();

      System.out.println("TestAudioCue() done");
   }

}


The next file is the AudioCue class. It contains two inner classes. AudioCuePlayer runs in its own thread. [The key "Audio Thread" classes are marked as such with comments. It is important to make sure nothing that blocks playback is added to this code.] When you open() or close() the AudioCue, that will handle setting up or destroying the SourceDataLine and thread that is used for playback. It is good to open() the cue a little bit in time prior to when you first play it. When the cue is open but not actively being played, it sends out zeros -- i.e., silence.

The other inner class is AudioCueCursor. This is a cursor/pointer into the sound data array. Unlike Clip, we have access to the sound data, which opens all sorts of possibilities. The AudioCueCursor currently just iterates through the array, and destroys itself when it is done. However, instead of destroying itself, we could add a flag to have it loop, or we could have it progress through the data by an increment other than 1 (and use linear interpolation to arrive at an output value). I have used both of these techniques successfully in my audio library.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
217  
218  
219  
220  
221  
222  
223  
224  
225  
226  
227  
228  
229  
230  
231  
232  
233  
234  
235  
236  
237  
238  
239  
240  
package jgo;

import java.io.IOException;
import java.net.URL;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.Line.Info;
import javax.sound.sampled.LineUnavailableException;

public class AudioCue
{
   private final float[] cue;
   private final CopyOnWriteArrayList<AudioCueCursor> cursors;
   
   private final int bufferSize = 64;
   private final int outBufferSize = bufferSize * 2;
   private final float[] buffer = new float[bufferSize];
   
   private final AudioFormat audioFormat;
   private final Info info;
   
   private Mixer mixer;
   public void setMixer(Mixer mixer)
   {
      this.mixer = mixer;
   }
   
   public volatile boolean playerRunning;
   
   public AudioCue(URL url) throws UnsupportedAudioFileException,
      IOException, LineUnavailableException
   {
      cue = loadURL(url);
      cursors = new CopyOnWriteArrayList<AudioCueCursor>();
     
      audioFormat = new AudioFormat(
                  AudioFormat.Encoding.PCM_SIGNED,
                  44100, 16, 2, 4, 44100, false);
     
      info = new DataLine.Info(SourceDataLine.class,
            audioFormat);      
   }
   
   private float[] loadURL(URL url) throws UnsupportedAudioFileException,
   IOException
   {
      AudioInputStream ais = AudioSystem.getAudioInputStream(url);

      int framesCount = 0;
      if (ais.getFrameLength() > Integer.MAX_VALUE >> 1)
      {
         System.out.println(
               "WARNING: Clip is too large to entirely fit!");
         framesCount = Integer.MAX_VALUE >> 1;
      }
      else
      {
         framesCount = (int)ais.getFrameLength();
      }
     
      // stereo output, so two entries per frame
      float[] temp = new float[framesCount * 2];
      long tempCountdown = temp.length;

      int bytesRead = 0;
      int bufferIdx;
      int clipIdx = 0;
      byte[] buffer = new byte[1024];
      while((bytesRead = ais.read(buffer, 0, 1024)) != -1)
      {
         bufferIdx = 0;
         for (int i = 0, n = (bytesRead >> 1); i < n; i ++)
         {
            if ( tempCountdown-- >= 0)
            {
               temp[clipIdx++] =
                     ( buffer[bufferIdx++] & 0xff )
                     | ( buffer[bufferIdx++] << 8 ) ;
            }
         }
      }
     
      // TODO QUESTION: is it better to do following in above loop
      // rather than iterating twice?
      for (int i = 0; i < temp.length; i++)
      {
         temp[i] = temp[i] / 32767f;
      }
     
      return temp;
   }  

   public void open()
   {
      AudioCuePlayer player = new AudioCuePlayer();
      Thread t = new Thread(player);
     
      t.setPriority(Thread.MAX_PRIORITY);    
      t.start();
      playerRunning = true;
   }

   public void close()
   {
      playerRunning = false;
   }
   
   public void play(float volume)
   {
      System.out.print("AudioCue.play called: " + System.currentTimeMillis());
   
      AudioCueCursor cursor = new AudioCueCursor();
      cursors.add(cursor);
      cursor.play(volume);
      System.out.println(", AudioCueCursor.play called:"
            + System.currentTimeMillis());
      System.out.println("(play) playing Cursors:" + cursors.size());
   }  
   
   private class AudioCueCursor
   {
      volatile boolean  isPlaying;
      int idx = 0;  
      float volume = 0;
     
      // TODO: make idx a float if/when we implement
      // variable speed play back, and add LERP
      void play(float volume)
      {
         idx = 0;
         this.volume = volume;
         isPlaying = true;
      }
     
      // Audio Thread Code
      public void read(float[] buffer)
      {
         if (isPlaying)
         {
            float audioData = 0;
            for (int i = 0, n = buffer.length; i < n; i++)
            {
               audioData = idx < cue.length ? cue[idx] : 0 ;
               buffer[i] += volume * audioData;
               idx++;
            }
         }
         isPlaying = idx < cue.length;
         if (!isPlaying)
         {
            cursors.remove(this);
            System.out.println("(read/remove) playing Cursors:" + cursors.size());
         }
      }
   }
   
   private class AudioCuePlayer implements Runnable
   {
      SourceDataLine sdl;
     
      AudioCuePlayer()
      {
         System.out.println("Opening SDL");
         try {
            sdl = getSDL();
            sdl.open();
            sdl.start();
         }
         catch (LineUnavailableException e)
         {
            e.printStackTrace();
         }
      }
     
      // Audio Thread Code
      public void run()
      {
         while(playerRunning)
         {
            // Start with 0-filled buffer, send out silence
            // if nothing playing.
            for (int i = 0; i < bufferSize; i++) buffer[i] = 0;
   
            for (AudioCueCursor acc:cursors)
            {
               if (acc.isPlaying)
               {
                  // sum data into buffer
                  acc.read(buffer);
               }
            }
           
            sdl.write(convertToAudioBytes(buffer), 0, outBufferSize);
         }
     
         System.out.println("closing sdl");
         sdl.drain();
         sdl.close();
         sdl = null;
      }
   }

   // Set up Java's output line
   private SourceDataLine getSDL() throws LineUnavailableException
   {
      if (mixer == null)
      {
         // default = Java's selection
         return (SourceDataLine)AudioSystem.getLine(info);
      }
      else
      {
         // an actively chosen Line
         return (SourceDataLine) mixer.getLine(info);
      }
   }

   // Audio Thread Code
   private byte[] convertToAudioBytes(float[] buffer)
   {
      byte[] audioBytes = new byte[outBufferSize];
     
      for (int i = 0; i < bufferSize; i++)
      {
         buffer[i] *= 32767;
         
         audioBytes[i*2] = (byte) buffer[i];
         audioBytes[i*2 + 1] = (byte)((int)buffer[i] >> 8 );
      }
   
      return audioBytes;
   }
}


Some more notes (I have a reputation for wordiness to maintain), and things to add:

> Audio Data form:
I chose to go ahead and convert the audio bytes to normalized float data (ranging from -1 to 1). We could have converted the bytes to shorts and done our audio mixing in that format. Maybe people will prefer that form in order to save a multiplication and division per frame. I think for many algorithms (not implemented yet) it is just easier to work with normalized floats.

> Volume changes during playback:
Well for short cues, you can just include the desired volumes with the play() command and taper or grow as you please with the successive plays. For longer cues, the question is whether to add a volume control that affects all concurrently playing cues (a "master volume") or for just a single playback instance. For this, my plan would be to create a hook in the AudioCueCursor, and make the AudioCueCursor a return value of the play() method. Changing volumes abruptly can create discontinuities in the sound data that results in clicks. My strategy has been to take commands to alter volume and incorporate them over the course of 1028 frames, in linear increments. This brings up another consideration: the volume parameter does not have a linear effect. You will probably want to put in something like a X^3 function if you want a semblance of, for example, volume 0.25 being one half as loud as 0.5.

> Audio playback buffer:
My choice of a buffer size is kind of arbitrary. Others probably have a better grasp of what values would allow the best throughput:safest trade offs. Please edit and let me know what works best for you. To be honest, the audio library I made for myself has, basically, a buffer of 1 (i.e., no buffer, just goes forward one frame at a time). This has worked out so far and allowed me to write a functional event system with per frame accuracy. But since the goal here is just to supplement the Java audio controls of Clip and SourceDataLine, it seemed logical to go for a greater throughput afforded by using a buffer. [This is part of the reason it took so long for me to write this--having to convert to using a buffer which none of my code uses.]

> Should I have stuck with start() instead of play()? It seems to me that play(), with parameters like volume, panning (to do), the addition of a AudioCueListener (also, to do), is the clearer command name.

> We probably should have a mono cue version that can be stereo panned. Panning stereo cues doesn't make a whole lot of sense to me. The panning algorithm could either use volume or using delay.

> I like doing more than just simple looping. I like having options to overlap the edges, and have done this in my own audio library. Cues with overlaps can have a nice smooth continuity where some loops have clicks over the breaks. It is mostly a matter of setting the overlap size (in frames) and deciding on the blending function (linear, or just add together, or various curves sometimes work best). I haven't done the following yet on my own library, but I think it would be neat to have a smoothly looping sound that is subject to real time speed and volume changes.

> Once one can do overlapping of edges, it is a short distance to extracting 'macro-granules' from the sound data body and stringing them together. This strategy can be used to create endless-non-repeating sounds such as campfires or brooks.

> TIMING:
Okay, the timing of the playbacks is going to be subject to some variance. This is kind of inevitable, as Java does not offer real time guarantees. In particular, the first play may lag by a millisecond or two, relative to the following plays, as we go from compiled to hot. This can be observed in the diagnostic comments I put in the code. Also, if you do a string of plays, all at exactly 100 millis, for example, chances are there will be some wobble to the timing. Another contributor to this is that we can't predict when Java switches between threads or when it chooses to garbage collect. Java DOES do a good time of maintaining playback steadiness of existing sound--and CAN provide very solid timing, but doing so requires tapping into the audio thread and counting elapsed frames. At least, that is what I do with the event system I wrote. Even so, the timing is pretty good. The AudioClip should be on a par with the Java Clip.
25  Discussions / Miscellaneous Topics / Re: Did VisualStudio just hose my Eclipse IDE? on: 2017-05-04 19:45:47
@Oskuro
I think you are right. Eclipse just runs from a jar file. I do remember a message about being unable to find the application but it is vague if the message also said anything about the registry -- which was part of my initial panic that the entire IDE was wiped out. I stupidly went straight to Add/Remove programs and was disturbed that the Eclipse IDE wasn't there. But of course it wouldn't be! It is just a jar file, running on the local jre.

Anyway, things are behaving now.
26  Discussions / Miscellaneous Topics / Re: Did VisualStudio just hose my Eclipse IDE? on: 2017-05-03 16:24:26
AFAIK it was just a regular version of Windows 10.

I am still getting a bit of twitchiness with this new Windows update. For example, even with all applications closed, when doing a normal shutdown last night an error message about an inaccessible memory location flashed by (went by too quick to read).

But I am now concluding that I was struck by a wave of paranoia. I tried searching for similar problems and nothing comes up. I'm sane enough to assume that my system would not be singled out, and that the Eclipse crash was a local glitch.

It just surprises me that a crash would result in shortcuts being wiped. OS's are complicated. Who knows, maybe some sort of "helpful cleanup" algorithm kicked in.
27  Discussions / Miscellaneous Topics / Did VisualStudio just hose my Eclipse IDE? on: 2017-05-03 02:35:08
On Sunday night, I installed the VisualStudio "Community" IDE for C++ on my desktop. It was around midnight. I opened and shut the app just to make sure it was working. Monday, went to day job.

Tuesday evening, I opened Eclipse Luna and was updating it with projects from my laptop Eclipse Luna, via a thumb drive. I had spent about 5 minutes and had opened a new project and was importing the source files, editing package names, and Eclipse closes without explanation.

I reboot. Windows decides at that point to do a major update I had scheduled for 11:59 tonight. Forty five minutes later, I'm told I now have some sort of "Developer" edition of Windows 10. The toolbar and desktop icons for Eclipse Luna are no where to be found.

OK, the workspace file is still there. The app itself is still in its folder and runs.

Damn! That shook me up. WTF. 

It is plausible that something I did in Eclipse caused it to crash and wipe out its own desktop and toolbar icons in the process, I suppose. Anyone else have anything like this happen? Or am I just paranoid?

By the way, C++ is a big, over-complicated mess. I don't like it. I'm committed to following through, though on the current project, implementing some of my sound tools and 3D SF/X ideas for use in Unreal. It would be a huge credibility boost and vindication to see this through, and maybe even result in a decent-paying game-programming job.

Would much rather be back putting most of my energy into Java development.
28  Game Development / Newbie & Debugging Questions / Re: Make an image fade in and out on: 2017-05-02 20:02:17
The best way to do animation in JavaFX is via the AnimationTimer. It has the best granularity, running at 60fps. I'd run all animations through a single AnimationTimer.

For a "flicker function," I'd consider having a variable that ranges from 0 to 1.0 and back (to use as an Opacity argument), with the increment being something like 0.2 (for 6 blinks per second), where the function is incremented by the AnimationTimer.

Images are generally displayed via ImageView, and ImageView has a setOpacity() method. If you have sprite sheet, won't each image of the sheet be displayed via an ImageView node? How are you handling sprite animation? The minimal sprite animation I've done was with a single ImageView that picks from a sprite sheet of images. If you do that, then you can use the setOpacity() for that ImageView to turn the hero visible/invisible.

The graphic image you use has transparent pixels for the non-hero portions, yes? (alpha = 0). If so, fading the hero sprite directly via setOpacity() should work as long as there is another graphic behind the hero.

If the whole screen is flickering, you are probably changing the opacity of the wrong thing!
29  Game Development / Newbie & Debugging Questions / Re: Curious about loopy loops on: 2017-04-26 17:35:44
Have you come across the term "Big O notation"?
That's a conceptual framework that is very helpful for discussing and analyzing exactly these sorts of issues.
30  Discussions / Miscellaneous Topics / Re: Annoying Interview Q on: 2017-04-26 17:28:42
I seem to amplify ambiguity--am always having to expend energy cutting away options. I'd do pretty bad with an interview question like that. But to be honest, a lot has to do with not sharing the same experience or context or points of reference with the other party.

Such a situation might not be the best fit anyway. Employers with not a lot of expertise in what they are hiring for probably really do need someone who's seen it all and can easily suss out their intentions and correct for their mistaken or limited ideas.

In other words, sometimes stupid questions are useful screening tools. I'm thinking, for example, the Nigerian Prince type scams: might as well make the initial proposal/contact full of obvious signals of the fraud involved because that fails faster with people discerning enough to likely reject the scam as they learn more about it.

In the music biz, it's kind of like being just good enough to play really well if people around you aren't making mistakes but being thrown if they get off, versus being good enough not to maintain and play well even when others bungle something in their parts.
Pages: [1] 2 3 ... 51
 
Archive (343 views)
2017-04-27 17:45:51

buddyBro (540 views)
2017-04-05 03:38:00

CopyableCougar4 (992 views)
2017-03-24 15:39:42

theagentd (1023 views)
2017-03-24 15:32:08

Rule (997 views)
2017-03-19 12:43:22

Rule (980 views)
2017-03-19 12:42:17

Rule (977 views)
2017-03-19 12:36:21

theagentd (1082 views)
2017-03-16 05:07:07

theagentd (1008 views)
2017-03-15 22:37:06

theagentd (779 views)
2017-03-15 22:32:18
List of Learning Resources
by elect
2017-03-13 14:05:44

List of Learning Resources
by elect
2017-03-13 14:04:45

SF/X Libraries
by philfrei
2017-03-02 08:45:19

SF/X Libraries
by philfrei
2017-03-02 08:44:05

SF/X Libraries
by SkyAphid
2017-03-02 06:38:56

SF/X Libraries
by SkyAphid
2017-03-02 06:38:32

SF/X Libraries
by SkyAphid
2017-03-02 06:38:05

SF/X Libraries
by SkyAphid
2017-03-02 06:37:51
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!