All Downloads are FREE. Search and download functionalities are using the official Maven repository.

phat.sensors.microphone.MicrophoneControl Maven / Gradle / Ivy

/*
 * Copyright (C) 2014 Pablo Campillo-Sanchez 
 *
 * This software has been developed as part of the 
 * SociAAL project directed by Jorge J. Gomez Sanz
 * (http://grasia.fdi.ucm.es/sociaal)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package phat.sensors.microphone;

import com.aurellem.capture.audio.MultiListener;
import com.aurellem.capture.audio.SoundProcessor;
import com.jme3.audio.AudioRenderer;
import com.jme3.audio.Listener;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ForkJoinPool;
import javax.sound.sampled.AudioFormat;
import phat.sensors.Sensor;
import phat.sensors.SensorListener;

/**
 *
 * @author Pablo
 */
public class MicrophoneControl extends Sensor implements SoundProcessor, Runnable {

    Control c;
    //private List bufferList;
    private int readIndex = 0;
    private int writeIndex = 0;
    private final int BUFFER_SIZE = 1470;
    private final int NUM_BUFFERS = 2;
    private int buf_i = 0;
    private byte[][] buffer = new byte[NUM_BUFFERS][BUFFER_SIZE];
    private AudioRenderer audioRenderer;
    private Listener listener = new Listener();
    private List> callables = new ArrayList>();

    /*
     @Override
     public void add(SensorListener sl) {
     super.add(sl);

     callables.add(new NotifyTask(this, sl));
     }*/
    public MicrophoneControl(String name, int bufferSize, AudioRenderer audioRenderer) {
        super(name);
        System.out.println("MicrophoneControl created!!");
        this.audioRenderer = audioRenderer;
        //buffer = new byte[bufferSize];
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        if (!enabled) {
            readIndex = 0;
            writeIndex = 0;
        }
    }
    
    public  T getListener(Class listener) {
        for(SensorListener l: listeners) {
            if(listener.isAssignableFrom(l.getClass())) {
                return (T) l;
            }
        }
        return null;
    }
    
    private void concurrentNotification(final MicrophoneData md) {
        ForkJoinPool pool = new ForkJoinPool();

        for (NotifyTask n : callables) {
            n.setMicrophoneData(md);
        }

        pool.invokeAll(callables);
    }

    private void serialNotification(final Sensor s, MicrophoneData md) {
        for (SensorListener sl : listeners) {
            sl.update(s, md);
        }
    }
    final Thread notifier = new Thread(this);
    boolean notifying = false;
    MicrophoneData md;

    @Override
    public void run() {
        while (notifying) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                synchronized (notifier) {
                    serialNotification(this, md);
                }
            }
        }
    }

    class NotifyTask implements Callable {

        SensorListener sensorListener;
        Sensor sensor;
        MicrophoneData sensorData;

        public NotifyTask(Sensor sensor, SensorListener sl) {
            this.sensorListener = sl;
            this.sensor = sensor;
        }

        public void setMicrophoneData(MicrophoneData sensorData) {
            this.sensorData = sensorData;
        }

        @Override
        public Void call() throws Exception {
            sensorListener.update(sensor, sensorData);
            return null;
        }
    }

    @Override
    public void process(ByteBuffer audioSamples, int numSamples, AudioFormat format) {

        if (enabled) {
            audioSamples.clear();
            int numBytes = (numSamples > BUFFER_SIZE) ? BUFFER_SIZE : numSamples;
            audioSamples.get(buffer[buf_i], 0, numBytes);

            synchronized (notifier) {
                md = new MicrophoneData(buffer[buf_i], format);
                buf_i = (buf_i + 1) % NUM_BUFFERS;
                notifyListeners(md);
            }
            //concurrentNotification(md);
            //serialNotification(MicrophoneControl.this, md);

            audioSamples.clear();
            /*
             new Thread() {
             public void run() {
             for(SensorListener sl: listeners)
             sl.update(MicrophoneControl.this, md);
             }
             }.start();*/
            
        }
    }

    public synchronized void updateReadIndex(int readedBytes) {
        readIndex += readedBytes;
    }

    public synchronized boolean areDiferents() {
        return readIndex != writeIndex;
    }

    @Override
    public Control cloneForSpatial(Spatial spatial) {
        return null;
    }
    private boolean init = false;

    private void init() {
        if (audioRenderer instanceof MultiListener) {
            MultiListener rf = (MultiListener) audioRenderer;
            rf.addListener(listener);
            rf.registerSoundProcessor(listener, this);
        }
        init = true;
        notifying = true;
        notifier.start();
    }

    @Override
    protected void controlUpdate(float tpf) {
        if (!init) {
            init();
        }
        if (listener != null) {
            listener.setLocation(spatial.getWorldTranslation());
            listener.setRotation(spatial.getWorldRotation());
        }
    }

    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {
    }

    @Override
    public void cleanup() {
        super.cleanUp();
        buffer = null;
        listener = null;
        notifying = false;
        notifier.interrupt();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy