Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm using Gtomee's audio spectrum decoder tutorials (from sample video or codes at GitHub) to create its own spawning pattern according to what music it played. It worked pretty nicely despite this decoder lets you decipher the frequency level or how high does the music's tone is, something like a do-re-mi.

    /**
     * 
     * Used to describes the behavior of the music.
     *
     */
    public static abstract class MusicUtils {
        public static KissFFT fft;
        public static Mpg123Decoder decoder;
        public static AudioDevice device;
        private static int nb = 0;
        private static boolean isPlaying = false;
        private static boolean isMusicPause = false;
        private static short[] samples = new short[2048];
        private static float[] spectrum = new float[2048];
        private static float[] maxValues = new float[2048];
        private static float[] freq = new float[3];
        private static final int NB_BARS = 31;
        private static Thread playback;

        /**
         * 
         * Set the constructor to enable deciphering music wave length.
         * 
         */
        public static void setMusicDecoder() {
            // Set freqeuncy for each target pad.
            freq[0] = 0;
            freq[1] = 0;
            freq[2] = 0;

            // Create temporary file at external drive and create music file from the internal drive.
            FileHandle externalFile = Gdx.files.external("tmp/audio-spectrum.mp3");
            Gdx.files.internal("musics/" + Flag.Music_Select.filename).copyTo(externalFile);

            // Set FFT and decoder.
            fft = new KissFFT(2048);
            decoder = new Mpg123Decoder(externalFile);
            device = Gdx.audio.newAudioDevice(decoder.getRate(), decoder.getChannels() == 1 ? true : false);

            // Set frequency max values.
            for(int i = 0; i < maxValues.length; i++) {
                maxValues[i] = 0;
            }
        }

        /**
         * 
         * Plays the sample music.
         * 
         */
        public static void play() {
            playback = new Thread(new Runnable() {
                @Override
                public void run() {
                    int readSamples = 0;

                    while(isPlaying) {
                        while(!Flag.Game_Over_Count.isGameOver && (readSamples = decoder.readSamples(samples, 0, samples.length)) > 0) {
                            fft.spectrum(samples, spectrum);
                            device.writeSamples(samples, 0, readSamples);
                            Gdx.app.log("SAMPLE LEVEL", String.valueOf(readSamples));
                            Gdx.app.log("SAMPLE RATE", String.valueOf(decoder.getRate()));
                            Gdx.app.log("SAMPLE LENGTH", String.valueOf(decoder.getLength()));

                            if(Game_Screen.isPaused) {
                                try {
                                    synchronized (decoder) {
                                        decoder.wait();
                                        Gdx.app.log("PLAY STATUS", "paused");
                                    }
                                } catch (InterruptedException e) {
//                                  e.printStackTrace();
                                    Gdx.app.log("STATUS", "Thread interrupted");
                                }
                            }
                        }

                        isPlaying = false;
                    }

                    Gdx.app.log("PLAY STATUS", String.valueOf(isPlaying));
                    System.out.println("IS PLAYING: " + isPlaying);
                }
            });

            playback.setDaemon(true);
            playback.start();
            isPlaying = true;
            Gdx.app.log("PLAY STATUS", String.valueOf(isPlaying));
        }

        public static void pause() {
//          isPlaying = false;
        }

        public static void resume() {
            synchronized (decoder) {
                decoder.notify();
                Gdx.app.log("PLAY STATUS", "resumed");
            }
        }

        public static Boolean isPlaying() {
            return isPlaying;
        }

        public static void stopPlaying() {
            isPlaying = false;
        }

        /**
         * 
         * Determines the sample audio level of the music.
         * 
         * @return The sample audio level.
         * 
         */
        public static float avg(int pos, int nb) {
            int sum = 0;

            for(int i = 0; i < nb; i++) {
                sum += spectrum[pos + i];
            }

            return (float) (sum/nb);
        }

        /**
         * 
         * Updates the sample audio level of the music.
         * 
         * @return The sample audio level.
         * 
         */
        public static void updateSamples() {
            for(int i = 0; i < NB_BARS; i++) {
                int x = 0;

                if(i < (NB_BARS/2)) {
                    x = NB_BARS/2 - i;
                } else {
                    x = i - NB_BARS/2;
                }

                nb = (samples.length/NB_BARS) / 2;
                if (avg(x, nb) > maxValues[x]) {
                    maxValues[x] = avg(x, nb);
                }

                if(i == 1) {
                    freq[0] =  avg(x, nb);
                    Gdx.app.log("FREQ 1", String.valueOf(freq[0]));
                }

                if(i == 15) {
                    freq[1] =  avg(x, nb);
                    Gdx.app.log("FREQ 1", String.valueOf(freq[1]));
                }

                if(i == 30) {
                    freq[2] =  avg(x, nb);
                    Gdx.app.log("FREQ 1", String.valueOf(freq[2]));
                }
            }
        }

        /**
         * 
         * Returns the frequency point of the audio.
         * 
         * @param index choose from 0 to 2. (Target Pads)
         * @return The frequency level.
         * 
         */
        public static float getFrequency(int index) {
            return freq[index];
        }

        /**
         * 
         * Returns the max frequency of the audio and updated dynamically.
         * 
         * @param index Max index is 31.
         * @return The max frequency.
         * 
         */
        public static float getMaxFrequency(int index) {
            return maxValues[index];
        }
    }

Then, I attached this class to a control class, which utilizes the spawn pattern.

        /**
         * 
         * Spawning rate of the spheres. (Max drop rate is 2,147,483,647.) <br>
         * Min Spawn Rate: 400,000,000 <br>
         * Max Spawn Rate: 1,900,000,000 <br>
         * 
         */
        public static void spawnNextTarget(boolean isPaused) {
            if(Control.MusicUtils.isPlaying() && !Flag.Game_Over_Count.isGameOver) 
            {
                Flag.timer = 0;
                if(!isPaused) {
                    // Left Target
                    if((TimeUtils.nanoTime() - Control.target.getLastDropTimeRate(0)) > 900000000) {
                        if((Control.MusicUtils.getFrequency(0) > (Control.MusicUtils.getMaxFrequency(1)/8)) &&
                                (Control.MusicUtils.getFrequency(0) < (Control.MusicUtils.getMaxFrequency(1)/2))) {
                            Control.target.dropRate1();
                        }
                    }

                    // Center Target
                    if((TimeUtils.nanoTime() - Control.target.getLastDropTimeRate(1) > 900000000)) {
                        if((Control.MusicUtils.getFrequency(1) > (Control.MusicUtils.getMaxFrequency(15)/8)) &&
                                (Control.MusicUtils.getFrequency(1) < (Control.MusicUtils.getMaxFrequency(15)/2))) {
                            Control.target.dropRate2();
                        }
                    }

                    // Right Target
                    if((TimeUtils.nanoTime() - Control.target.getLastDropTimeRate(2) > 900000000)) {
                        if((Control.MusicUtils.getFrequency(2) > (Control.MusicUtils.getMaxFrequency(17)/8)) &&
                                (Control.MusicUtils.getFrequency(2) < (Control.MusicUtils.getMaxFrequency(20)/2))) {
                            Control.target.dropRate3();
                        }
                    }
                }

                Flag.Game_Over_Count.isResult = false;
            } else {
                Flag.timer += 100;
                Gdx.app.log("TIMER RESULT", String.valueOf(Flag.timer));
                if(Flag.timer == 25000 && !Flag.Game_Over_Count.isGameOver) { // --> RESULT SCREEN FLAG
                    Flag.Game_Over_Count.isResult =  true;

                    // Check for highscore updates.
                    if(Screen_View.Game_Stage_View.score >= Flag.highscore) {
                        Gdx.app.log("TRACK", String.valueOf(Flag.Music_Select.index));
                        HighScore.Track.saveHighestScore(Screen_View.Game_Stage_View.score, Flag.Music_Select.index);
                    } else {
                        Gdx.app.log("TRACK", String.valueOf(Flag.Music_Select.index));
                        System.out.println("Missed it!");
                    }
                } else if((Flag.timer == 1000) && Flag.Game_Over_Count.isGameOver) { // --> GAME OVER SCREEN FLAG
                    Flag.Game_Over_Count.isResult =  true;
                } else if((Flag.timer == 1100) && Flag.Game_Over_Count.isGameOver) { // --> SFX
                    Sfx.gameOver.play(1f);
                }

//              System.out.println(Flag.timer);
            }

//          System.out.println("Current Freq: " + Control.MusicUtils.getFrequency() + " | Max Freq: " + (Control.MusicUtils.getMaxFrequency(1)/3));

//          System.out.println("LDTR 0: xxxxxxxxxx");
//          System.out.println("LDTR 1: " + (TimeUtils.nanoTime()));
//          System.out.println("LDTR 2: " + (Control.target.getLastDropTimeRate(1)));
//          System.out.println("LDTR 3: " + (TimeUtils.nanoTime() - Control.target.getLastDropTimeRate(2)));
        }

The problem is that when I tested it onto the device, the spawning pattern appeared nearly identical when I switch and play different music. Do you think there is something wrong with the decoder? What should I do? I have to know if when a frequency or tone is low, it spawns on the left pad, the mid tone is on the center, and the right pad will spawn only for the highest tone. In case if there is the all three level of tones played simultaneously, then, it will spawn all together.

share|improve this question
1  
I think you need to do a bit more leg work on this one. Do some more debugging to track down exactly where the issue is. Then narrow down the code you're showing here and be a bit more concise on what the problem is. –  Byte56 Nov 18 '13 at 15:19
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.