Android pulse an icon when .wav volume changes

161 views Asked by At

I'm building an android app that pulses an icon - simple pulse, 2x size at loudest volume and 1x at no volume - based on audio. Worth noting my min api is 15.

The user selects the mode (file)to play and I use AudioTrack to play it back on an infinite loop. Each wav sample ranges from < second to 2 or 3 seconds. Audiotrack lets me set the volume and pitch in real-time based on user input (SoundPool wasn't correctly changing pitch in Kitkat). As the volume changes within each audiotrack, I'm trying to shrink and grow the icon. So far I've tried visualizer to get the waveform and fft data as the track is playing, but I'm not sure that's correct.

Is there a way to get the (nearest possible) real-time db changes from an audiotrack? The wave form function seems to always be between 108 and 112, so I don't think I'm using it correctly. The easiest pulse.wav example is here

My audiotrack init using a byte[] from pcm data

AudioTrack mAudioTrack = new AudioTrack(AudioAudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, getMinBuffer(sound), AudioTrack.MODE_STATIC);
mAudioTrack.write(mSound, 0, mSound.length);
mAudioTrack.setLoopPoints(0, (int)(mSound.length / 4), -1);

My Visualizer

Visualizer mVisualizer = new Visualizer(mAudioTrack.getAudioSessionId());
mVisualizer.setEnabled(false);
mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener {
    @Override
    public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {
        double sum = 0;

        for (int i = 0; i < bytes.length; i++) {
            sum += Math.abs(bytes[i]) * Math.abs(bytes[i]);
        }

        double volume = (double) Math.sqrt(1.0d * sum / bytes.length);
        //THIS IS THE RESIZE FUNCTION//
        //resizeHeart((double) volume);
        System.out.println("Volume: " + volume); //always prints out between 108 and 112.
    }
    @Override
    public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {
        //not sure what to do here.
    }
}, Visualizer.getMaxCaptureRate() / 2, true, true);
mVisualizer.setEnabled(true);
1

There are 1 answers

1
jaket On

The problem is that you're treating the bytes as samples even though you've specified a 16-bit sample size. Try something like this (note the abs is unnecessary since you're squaring anyway):

    for (int i = 0; i < bytes.length/2; i+=2) {
        int sample = bytes[i] << 8 || bytes[i+1];
        sum += sample * sample;
    }