Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (535)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Synchronizing events with a streaming audio soundtrack?  (Read 1362 times)
0 Members and 1 Guest are viewing this topic.
Offline taifunbrowser

Senior Newbie





« Posted 2007-06-14 23:01:35 »

Post revision v.2: (hopefully more fun to read)

I want to play a streaming ogg file, and fire an event at second 8.043 of the song.

Things I have available: Jogl and Joal both running, but I can use anything at this point: I'm desperate! What audio systems will give me the capability to get playback position?

http://beam.to/jtouhou - the JTouhou project! Mixed 3d and 2d, a multiplatform port for the classic dojin-soft series by Shanghai alice!
Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #1 - Posted 2007-06-15 08:57:12 »

If you have the ogg streaming in place, just count the (decoded) samples you send to the soundcard to get the playback position.

Offline taifunbrowser

Senior Newbie





« Reply #2 - Posted 2007-06-15 15:40:58 »

Yes, I'm looking for code that does that Tongue

how many samples per second for ogg? isn't it variable bitrate?

edit: What I've got so far:

         new Thread(new Runnable(){
         public void run(){               
            try {
               Thread.sleep(500);
            } catch (Exception e){ }
            while(true){               
               try {
                  Thread.sleep(1); //Every ms update
               } catch (Exception e){ }
               int[] values = new int[1];
               al.alGetSourcei(sourceID, AL.AL_BYTE_OFFSET, values,0);
               Position_MS = (int)(10000.0*(OggStreamer.this.totalBytes+values[0])/ OggStreamer.this.numBytesPerSample/ OggStreamer.this.numChannels / rate / 10.0);
               if (Position_MS>4926)
                  System.out.println(Position_MS);
            }
         }
      }).start();

Now, this is very strange: AL_AL_BYTE_OFFSET remains unchanged every 20 iterations!!! Why is it only updated so infrequently!? This could kill my game

Does ANYONE have some better ideas?

http://beam.to/jtouhou - the JTouhou project! Mixed 3d and 2d, a multiplatform port for the classic dojin-soft series by Shanghai alice!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #3 - Posted 2007-06-15 16:21:10 »

Quote
how many samples per second for ogg? isn't it variable bitrate?

That's why I said *decoded* samples. If you stream an ogg file, it is decoded on the fly, and when the ogg file is 44.1KHz for example, you're decoding 44100 samples a second (or 44100 * 2 for stereo).
Take a look at jorbis at http://www.jcraft.com/jorbis/, download the sourceand try to find in the code where the ogg file is decoded and where it sends the decoded samples to JavaSound. At that point you can add your counter (maybe jorbis even already has functionality for that, I'm not sure).

Offline taifunbrowser

Senior Newbie





« Reply #4 - Posted 2007-06-15 16:23:44 »

k, modified my above post in between you posting Tongue

but ya, I figured out the samplerate for my file by looking at sample programs, it is currently working, but the resolution is very low: al_bytes_offset appears to be updated very infrequently

http://beam.to/jtouhou - the JTouhou project! Mixed 3d and 2d, a multiplatform port for the classic dojin-soft series by Shanghai alice!
Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #5 - Posted 2007-06-15 16:41:28 »

The resolution being low could be due to buffering, or maybe the offset is only updated per block in the ogg decoder (I'm not sure, I can't see what you're doing exactly just by looking at the code you posted).
If you want sub ms resolution, I'd really count the individual decoded samples in the ogg decoder, and add a getter somewhere to calculate the offset in MS from the samples offset.

Offline taifunbrowser

Senior Newbie





« Reply #6 - Posted 2007-06-15 17:18:39 »

Well, the problem is that I think that I need to use the BYTE_OFFSET, because that actuall says how many bytes have been played by the mixer (!!!) , but, for somereason, the resolution appears to be EXACTLY 10 ms. Soooo, I made a sub loop, that watches for its change.

So, we store the value of BYTE_OFFSET in a temp, and if it doesnt change between iteration, we increment a millisecond. If it changes, we're at the new time.

cool Cheesy

edit: nahhhh actually that doesn't work either Sad looks like I'll have to deal with my 10 ms resolution Sad

http://beam.to/jtouhou - the JTouhou project! Mixed 3d and 2d, a multiplatform port for the classic dojin-soft series by Shanghai alice!
Offline taifunbrowser

Senior Newbie





« Reply #7 - Posted 2007-06-15 18:06:05 »

THE RESULT OF THIS THREAD: This method gives you 10 ms resolution to ACTUAL MIXER PLAYBACK TIME. That is GOOD ENOUGH. (I'm making a music game, and it is spot on. Seriously, I stress tested it: It looks right on the beat.)

Code to synchronize audio through JOAL, because you can't get this capability with javasound (because theres an unpredictable delay from javasound to mixer playback.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
new Thread(new Runnable(){
         public void run(){
            while(true){
               try {
                  Thread.sleep(1);
               } catch (Exception e){ };
               int[] values = new int[1];
               al.alGetSourcei(sourceID, AL.AL_BYTE_OFFSET, values,0);
               long temp_Position_MS = (int)(1000.0*(totalBytes-BUFFER_SIZE*2+values[0])/ numBytesPerSample/ numChannels / rate);
               if (Position_MS == temp_Position_MS) //THIS IS OPTIONAL, ITS JUST SO THAT YOU NEVER "HIT THE SAME TIME" TWICE, because BYTE_OFFSET has 10 ms resolution, slower than our iteration.
                 Position_MS++;
               else
                  Position_MS = temp_Position_MS;
            }
         }
      }).start();


Somewhere deep in the stream code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
byte[] pcm = new byte[BUFFER_SIZE];
      int size = 0;

      try {
         if ((size = oggDecoder.read(pcm)) <= 0)
            return false;
      } catch (Exception e) {
         e.printStackTrace();
         return false;
      }

      totalBytes += size;


The tester code:
1  
2  
3  
4  
5  
6  
7  
double gap = .096;
            double bpm = 198.757763975155279;
            for (int a = 0; a < 400; a++){ //This if a very bad way to do it :p I'll fix it soon.
              if (audio.offOf((int)(1000*(gap+a*(60/bpm))))<20){
                  Trenderer.draw("BAM!", (int)myCharacter.getX(), (int)myCharacter.getY());
               }
            }


and

1  
2  
3  
4  
   public long offOf(int target){
      long returnee = Position_MS - target;
      return returnee < 0?-returnee:returnee;
   }

http://beam.to/jtouhou - the JTouhou project! Mixed 3d and 2d, a multiplatform port for the classic dojin-soft series by Shanghai alice!
Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #8 - Posted 2007-06-15 18:42:10 »

Quote
because you can't get this capability with javasound (because theres an unpredictable delay from javasound to mixer playback.

I know what you mean, it is caused by javasounds internal buffering and the sound driver's buffering that lead to methods for measuring returning values with low coarse precision (I've been fighting with that issue too). It can still be done perfectly with JavaSound though, you just have to measure the time before the audio data enters this buffering and take the latency into account (defined by the size of the buffers), and not rely on measurement values from JavaSound.

But I'm glad you got it working fine in OpenAL, and yes, 10ms precision is probably just fine for a music game.

Pages: [1]
  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.

Riven (7 views)
2014-07-29 12:53:52

Dwinin (7 views)
2014-07-29 10:59:34

E.R. Fleming (23 views)
2014-07-29 03:07:13

E.R. Fleming (9 views)
2014-07-29 03:06:25

pw (39 views)
2014-07-24 01:59:36

Riven (39 views)
2014-07-23 21:16:32

Riven (26 views)
2014-07-23 21:07:15

Riven (28 views)
2014-07-23 20:56:16

ctomni231 (59 views)
2014-07-18 06:55:21

Zero Volt (51 views)
2014-07-17 23:47:54
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!