Android Open Source - android-binarual-beats-generator Binaural Manager






From Project

Back to project page android-binarual-beats-generator.

License

The source code is released under:

GNU General Public License

If you think the Android project android-binarual-beats-generator listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*******************************************************************************
 * Copyright (c) 2010 Robert Bermani./*from   ww  w  .  j  a va  2  s.  co  m*/
 * All rights reserved. This program and its accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which is included with this distribution and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *     Robert Bermani - initial API and implementation
 ******************************************************************************/
package rbermani.android.binaural;

import android.content.Context;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.PowerManager;



public class BinauralManager {

  final int sineTableSz = 16384;

  private static final short NOISE_ADJUST = 12;
  private static final int NOISE_AMPLITUDE = (Short.MAX_VALUE);
  private static final short NOISE_BANDS = 9;
  private static final short RAND_MULT = 75;

  private AndroidAudioDevice device;

  private volatile boolean continueRunning = true;
  private double frequencyLeft, frequencyRight;

  private boolean pinkNoiseEnable = false;

  private volatile int leftChanIncrement;
  private volatile int rightChanIncrement;
  private int leftOffset;
  private int rightOffset;
  private volatile Thread backgroundThread;
  private int bufferLength;


  private Noise noiseTable[];
  private int noiseTableOffset = 1;
  private int rand0 = 0, rand1 = 0;

  private int randomSeed;

  private short sineTable[] = new short[sineTableSz];
  private int noiseBuffer[] = new int[sineTableSz];

  private MediaPlayer nMediaPlayer;
  private float pinkNoiseAmpPref = .020f;
  private float binauralAmpPref  = 0.05f;
  private float backgroundLoopTrack = 0.5f;

  public BinauralManager() {

    device = new AndroidAudioDevice( );
    
    
    this.bufferLength = device.getMinSize();
    this.randomSeed = 3;

    this.leftOffset = 0;
    this.rightOffset = 0;

    this.noiseTable = new Noise[NOISE_BANDS];

    for (int i = 0; i < noiseTable.length; i++)
      noiseTable[i] = new Noise();


    // Populate sine lookup table
    for (int a = 0; a < sineTableSz; a++) {
      sineTable[a] = (short) (Short.MAX_VALUE *
          Math.sin((2 * Math.PI * a) / sineTableSz));
    }

    // Populate pink noise lookup table
    for (int a = 0; a < noiseBuffer.length; a++) {
      noiseBuffer[a] = (genPinkNoiseSample() << 16);

    }


    backgroundThread = new Thread(new Runnable () {
      public void run() {

        while( continueRunning )
        {
          device.writeRaw( getMixedSamples() );

        }    

      }
    });
    

  }

  public boolean isPlaying(){
    return continueRunning;
  }
  private class Noise {
    public int value;
    public int increment;

    public Noise()
    {
      this.value = 0;
      this.increment = 0;
    }
  }

  public void loadBackgroundTrack(Context parent){

    if (nMediaPlayer == null){
    nMediaPlayer = MediaPlayer.create(parent, R.raw.waters);
    nMediaPlayer.setLooping(true);
    } 
    
    if (nMediaPlayer != null){
      //nMediaPlayer.setWakeMode(parent, PowerManager.PARTIAL_WAKE_LOCK);
      nMediaPlayer.setVolume(backgroundLoopTrack, backgroundLoopTrack);
    }
    
    
  }

  public void releaseBackgroundTrack(){
    if (nMediaPlayer != null){
      nMediaPlayer.release();
      } 
  }
  
  
  public void enableBackgroundTrack(){
    
    
    if (nMediaPlayer != null){
        if (!nMediaPlayer.isPlaying()){
        nMediaPlayer.start();}
      } 
    
  }

  public void disableBackgroundTrack(){
    if (nMediaPlayer != null){
      if (nMediaPlayer.isPlaying())
        nMediaPlayer.pause();
    }
  }
  public void setMixerLevels(int pinkNoiseAmp,
      int binauralAmp, int backgroundLoopAmp) {

    this.pinkNoiseAmpPref = 0.020f*(pinkNoiseAmp/100f+0.01f);
    this.binauralAmpPref =  0.058f*(binauralAmp/100f+0.01f);
    this.backgroundLoopTrack = 0.5f*(backgroundLoopAmp/100f+0.01f);

  }
  public void start() {
    continueRunning = true;

    try {
      if (!backgroundThread.isAlive()){  
        backgroundThread.start();
      }

    } catch (IllegalThreadStateException e) {
      backgroundThread = new Thread(new Runnable () {
        public void run() {

          while( continueRunning )
          {
            device.writeRaw( getMixedSamples() );

          }    

        }
      });
      backgroundThread.start();
    }  



  }

  public void stop() {

    continueRunning = false;

    if (nMediaPlayer != null){
      disableBackgroundTrack();
      
    } 


  }
  
  public void terminate() {

    continueRunning = false;

    if (nMediaPlayer != null){
      nMediaPlayer.stop();
      this.releaseBackgroundTrack();
      
    } 

    

  }
  public synchronized void configureBeats(double carrFrequency, double resFrequency){
    frequencyLeft = carrFrequency - (resFrequency/2);
    frequencyRight = carrFrequency + (resFrequency/2);

    leftChanIncrement =  (int) (frequencyLeft / 44100 * sineTableSz); // increment into sine table
    rightChanIncrement = (int) (frequencyRight / 44100 * sineTableSz);

    leftOffset = 0;
    rightOffset = 0;

  }  

  public void configureBeats(double carrFrequency, double resFrequency, int pinkNoiseAmp,
      int binauralAmp, int backgroundLoopAmp){

    configureBeats(carrFrequency, resFrequency);
    setMixerLevels(pinkNoiseAmp, binauralAmp, backgroundLoopAmp);

  }

  public short[] getMixedSamples() 
  {
    short outputBuffer[] = new short[bufferLength];
    int leftChanMix = 0, rightChanMix = 0;
    noiseTableOffset = 0;
    int leftChanIncrement = this.leftChanIncrement;
    int rightChanIncrement = this.rightChanIncrement;
    int leftOffset = this.leftOffset;
    int rightOffset = this.rightOffset;

    for( int i = 0; i < outputBuffer.length-1; i += 2 )
    {

      noiseTableOffset++;
      noiseTableOffset &= sineTableSz - 1;

      leftOffset &= sineTableSz - 1;
      leftChanMix = (int) (binauralAmpPref*(sineTable[leftOffset] << 16));
      leftOffset += leftChanIncrement;

      rightOffset &= sineTableSz - 1;
      rightChanMix = (int) (binauralAmpPref*(sineTable[rightOffset] << 16));
      rightOffset += rightChanIncrement;
      if (pinkNoiseEnable){

        leftChanMix += pinkNoiseAmpPref*noiseBuffer[noiseTableOffset];
        rightChanMix += pinkNoiseAmpPref*noiseBuffer[noiseTableOffset];

      }

      // white noise dithering
      rand0 = rand1;
      rand1 = (rand0 * 0x660D + 0xF35F) & 0xFFFF;

      if (leftChanMix <= 0x7FFF0000) leftChanMix += rand0;
      if (rightChanMix <= 0x7FFF0000) rightChanMix += rand0;

      outputBuffer[i] = (short) (leftChanMix >> 16);
      outputBuffer[i+1] = (short) (rightChanMix >> 16);

    }

    return outputBuffer;
  }

  public void pause(){
    device.pauseAudio();
  }

  public void setPinkNoise(boolean enable){
    this.pinkNoiseEnable = enable;
  }

  private short genPinkNoiseSample() 
  {

    int mixAccumulator;
    int count = 1;
    int offset;

    offset = noiseTableOffset++;

    int tmpValue;

    randomSeed *= RAND_MULT % 131074;
    mixAccumulator = ((randomSeed - 256)) * (NOISE_AMPLITUDE / 256 / (NOISE_BANDS + 1));

    for (int i = 0; (count & offset) != 0 && (i < noiseTable.length); i++) 
    {
      randomSeed *= RAND_MULT % 131074;
      tmpValue = (randomSeed - 256) * (NOISE_AMPLITUDE / 256 / (NOISE_BANDS + 1));
      count *= 2;

      noiseTable[i].increment = (tmpValue - noiseTable[i].value) / count;
      noiseTable[i].value += noiseTable[i].increment;
      mixAccumulator += noiseTable[i].value;
    }

    for (int i = 0; i < noiseTable.length; i++)
    {
      noiseTable[i].value += noiseTable[i].increment;
      mixAccumulator += noiseTable[i].value;
    }

    return ((short)mixAccumulator);

  }

  //  private class outputSound extends AsyncTask {
  //    protected Object doInBackground(Object... arg0)
  //    {
  //
  //      while( continueRunning )
  //      {
  //        device.writeRaw( getMixedSamples() );
  //      }        
  //      
  //      return null;
  //    }
  //  }

}




Java Source Code List

rbermani.android.binaural.AboutActivity.java
rbermani.android.binaural.AndroidAudioDevice.java
rbermani.android.binaural.BinauralManager.java
rbermani.android.binaural.MainActivity.java
rbermani.android.binaural.PreferencesDlg.java
rbermani.android.binaural.VoiceType.java
rbermani.android.binaural.Voice.java
rbermani.android.widgets.SeekBarPreference.java