Updates pull request from Roman Tsypuk to convert the build system from

ant to gradle.  Removes linux and windows application launch scripts and
produces an executable jar with all resources included.
This commit is contained in:
Denny
2017-12-17 07:28:03 -05:00
parent a1535c4157
commit 9316599dec
981 changed files with 8368 additions and 9049 deletions

View File

@@ -0,0 +1,433 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
*
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.complex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
/**
* Complex sample and related utility methods
*/
public class Complex implements Serializable
{
private final static Logger mLog =
LoggerFactory.getLogger( Complex.class );
private static final long serialVersionUID = 1L;
private float mLeft;
private float mRight;
public Complex( float left, float right )
{
mLeft = left;
mRight = right;
}
public Complex()
{
this( 0.0f, 0.0f );
}
public void setInphase( float inphase )
{
mLeft = inphase;
}
public void setQuadrature( float quadrature )
{
mRight = quadrature;
}
public void setValues( float inphase, float quadrature )
{
mLeft = inphase;
mRight = quadrature;
}
public Complex copy()
{
return new Complex( mLeft, mRight );
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( "I:" );
sb.append( mLeft );
sb.append( " Q:" );
sb.append( mRight );
return sb.toString();
}
/**
* Returns a new sample representing the conjugate of this one
*/
public Complex conjugate()
{
return new Complex( mLeft, -mRight );
}
/**
* Multiplies this sample by the scalor value
*/
public void multiply( float scalor )
{
mLeft *= scalor;
mRight *= scalor;
}
public static Complex multiply( Complex sample, float scalor )
{
return new Complex( sample.left() * scalor,
sample.right() * scalor );
}
/**
* Calculates the inphase component of multiplying two complex numbers, A and B.
*/
public static float multiplyInphase( float inphaseA, float quadratureA, float inphaseB, float quadratureB )
{
return ( inphaseA * inphaseB ) - ( quadratureA * quadratureB );
}
/**
* Calculates the quadrature component of multiplying two complex numbers, A and B.
*/
public static float multiplyQuadrature( float inphaseA, float quadratureA, float inphaseB, float quadratureB )
{
return ( quadratureA * inphaseB ) + ( inphaseA * quadratureB );
}
/**
* Multiplies this sample by the multiplier sample
*/
public void multiply( Complex multiplier )
{
float inphase = multiplyInphase( inphase(), quadrature(),
multiplier.inphase(), multiplier.quadrature() );
float quadrature = multiplyQuadrature( inphase(), quadrature(),
multiplier.inphase(), multiplier.quadrature() );
mLeft = inphase;
mRight = quadrature;
}
/**
* Multiplies both samples returning a new sample with the results
*/
public static Complex multiply( Complex sample1, Complex sample2 )
{
float inphase = multiplyInphase( sample1.inphase(), sample1.quadrature(),
sample2.inphase(), sample2.quadrature() );
float quadrature = multiplyQuadrature( sample1.inphase(), sample1.quadrature(),
sample2.inphase(), sample2.quadrature() );
return new Complex( inphase, quadrature );
}
public static Complex multiply( Complex sample,
Float inphase, Float quadrature )
{
float i = multiplyInphase( sample.inphase(), sample.quadrature(),
inphase, quadrature );
float q = multiplyQuadrature( sample.inphase(), sample.quadrature(),
inphase, quadrature );
return new Complex( i, q );
}
public static Complex multiply( Float inphase, Float quadrature, Complex sample )
{
float i = multiplyInphase( inphase, quadrature, sample.inphase(), sample.quadrature() );
float q = multiplyQuadrature( inphase, quadrature, sample.inphase(), sample.quadrature() );
return new Complex( i, q );
}
public static Complex multiply( float inphaseA, float quadratureA, float inphaseB, float quadratureB )
{
float i = multiplyInphase( inphaseA, quadratureA, inphaseB, quadratureB );
float q = multiplyQuadrature( inphaseA, quadratureA, inphaseB, quadratureB );
return new Complex( i, q );
}
/**
* Adds the adder sample value to this sample
*/
public void add( Complex adder )
{
mLeft += adder.left();
mRight += adder.right();
}
/**
* Adds the two complex samples returning a new complex sample with the result
*/
public static Complex add( Complex first, Complex second )
{
return new Complex( first.left() + second.left(),
first.right() + second.right() );
}
/**
* Adds the two complex samples returning a new complex sample with the result
*/
public static Complex subtract( Complex first, Complex second )
{
return new Complex( first.left() - second.left(),
first.right() - second.right() );
}
/**
* Magnitude of this sample
*/
public float magnitude()
{
return (float)Math.sqrt( magnitudeSquared() );
}
public static float magnitude( float inphase, float quadrature )
{
return (float)Math.sqrt( ( inphase * inphase ) + ( quadrature * quadrature ) );
}
/**
* Magnitude squared of this sample
*/
public float magnitudeSquared()
{
return norm();
}
/**
* Norm of this sample = ( i * i ) + ( q * q )
*/
public float norm()
{
return (float)( ( inphase() * inphase() ) +
( quadrature() * quadrature() ) );
}
/**
* Returns the vector length to 1 (unit circle)
*/
public void normalize()
{
float magnitude = magnitude();
if( magnitude != 0 )
{
multiply( (float)( 1.0f / magnitude() ) );
}
}
/**
* Returns the vector length to 1 (unit circle),
* avoiding square root multiplication
*/
public void fastNormalize()
{
multiply( (float)( 1.95f - magnitudeSquared() ) );
}
public float left()
{
return mLeft;
}
public float right()
{
return mRight;
}
public float inphase()
{
return mLeft;
}
/**
* Absolute value of in-phase component
*/
public float inPhaseAbsolute()
{
return Math.abs( mLeft );
}
public float quadrature()
{
return mRight;
}
/**
* Absolute value of quadrature component
*/
public float quadratureAbsolute()
{
return Math.abs( mRight );
}
public float x()
{
return mLeft;
}
public float y()
{
return mRight;
}
public float real()
{
return mLeft;
}
/**
* Absolute value of real component
*/
public float realAbsolute()
{
return Math.abs( mLeft );
}
public float imaginary()
{
return mRight;
}
/**
* Absolute value of imaginary component
*/
public float imaginaryAbsolute()
{
return Math.abs( mRight );
}
/**
* Returns the greater absolute value between left and right values
*/
public float maximumAbsolute()
{
if( Math.abs( mLeft ) > Math.abs( mRight ) )
{
return Math.abs( mLeft );
}
else
{
return Math.abs( mRight );
}
}
/**
* Creates a new complex sample representing the angle with unit circle
* magnitude
* @param angle in radians
* @return
*/
public static Complex fromAngle( float angle )
{
return new Complex( (float)Math.cos( angle ),
(float)Math.sin( angle ) );
}
/**
* Angle of this sample in radians
*/
public float angle()
{
return (float)Math.atan2( y(), x() );
}
/**
* Constrains the i and q quantities to +/- value.
*
* @param value - maximum absolute value
*/
public void clip( float value )
{
if( mLeft > value )
{
mLeft = value;
}
else if( mLeft < -value )
{
mLeft = -value;
}
if( mRight > value )
{
mRight = value;
}
else if( mRight < -value )
{
mRight = -value;
}
}
/**
* Angle of this sample in degrees
*/
public float polarAngle()
{
return (float)Math.toDegrees( angle() );
}
/**
* Provides an approximate magnitude value for this sample.
*/
public float envelope()
{
return envelope( mLeft, mRight );
}
public static float envelope( float inphase, float quadrature )
{
float inphaseAbsolute = Math.abs( inphase );
float quadratureAbsolute = Math.abs( quadrature );
if( inphaseAbsolute > quadratureAbsolute )
{
return inphaseAbsolute + ( 0.4f * quadratureAbsolute );
}
else
{
return quadratureAbsolute + ( 0.4f * inphaseAbsolute );
}
}
public static void main( String[] args )
{
double angle = Math.PI; //180 degrees
Complex s1 = new Complex( (float)Math.sin( angle ), (float)Math.cos( angle ) );
Complex tap = new Complex( 1.0f, -0.1f );
Complex convolved = Complex.multiply( s1, tap );
mLog.debug( "s: " + s1.toString() +
" t: " + tap.toString() +
" convolved: " + convolved.toString() );
}
}

View File

@@ -0,0 +1,26 @@
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Buffer;
import java.util.Arrays;
public class ComplexBuffer extends Buffer
{
/**
* Wrapper around float array containing interleaved I/Q samples
*/
public ComplexBuffer( float[] samples )
{
super( samples );
}
/**
* Creates a deep copy of the buffer
*/
public ComplexBuffer copyOf()
{
float[] copy = Arrays.copyOf( mSamples, mSamples.length );
return new ComplexBuffer( copy );
}
}

View File

@@ -0,0 +1,35 @@
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Listener;
/**
* Real sample buffer to stream converter
*/
public class ComplexBufferToStreamConverter implements Listener<ComplexBuffer>
{
private ComplexSampleListener mListener;
public void dispose()
{
mListener = null;
}
@Override
public void receive( ComplexBuffer buffer )
{
if( mListener != null )
{
float[] samples = buffer.getSamples();
for( int x = 0; x < samples.length; x += 2 )
{
mListener.receive( samples[ x ], samples[ x + 1 ] );
}
}
}
public void setListener( ComplexSampleListener listener )
{
mListener = listener;
}
}

View File

@@ -0,0 +1,72 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
*
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.Provider;
import java.util.ArrayList;
import java.util.List;
public class ComplexSampleAssembler implements Listener<Complex>,
Provider<List<Complex>>
{
private ArrayList<Complex> mBuffer;
private int mBufferSize;
private Listener<List<Complex>> mListener;
public ComplexSampleAssembler( int bufferSize )
{
mBufferSize = bufferSize;
mBuffer = new ArrayList<>();
}
public void dispose()
{
mBuffer.clear();
mListener = null;
}
@Override
public void receive( Complex sample )
{
mBuffer.add( sample );
if( mBuffer.size() >= mBufferSize )
{
if( mListener != null )
{
mListener.receive( mBuffer );
}
mBuffer = new ArrayList<>();
}
}
@Override
public void setListener( Listener<List<Complex>> listener )
{
mListener = listener;
}
@Override
public void removeListener( Listener<List<Complex>> listener )
{
mListener = null;
}
}

View File

@@ -0,0 +1,76 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
*
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.complex;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Broadcasts received float samples to multiple listeners
*/
public class ComplexSampleBroadcaster implements ComplexSampleListener
{
private CopyOnWriteArrayList<ComplexSampleListener> mListeners =
new CopyOnWriteArrayList<ComplexSampleListener>();
@Override
public void receive( float i, float q )
{
broadcast( i, q );
}
/**
* Clear listeners to prepare for garbage collection
*/
public void dispose()
{
mListeners.clear();
}
public boolean hasListeners()
{
return !mListeners.isEmpty();
}
public int getListenerCount()
{
return mListeners.size();
}
public void addListener( ComplexSampleListener listener )
{
mListeners.add( listener );
}
public void removeListener( ComplexSampleListener listener )
{
mListeners.remove( listener );
}
public void clear()
{
mListeners.clear();
}
public void broadcast( float i, float q )
{
for( ComplexSampleListener listener: mListeners )
{
listener.receive( i, q );
}
}
}

View File

@@ -0,0 +1,25 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
*
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.complex;
import java.util.List;
public interface ComplexSampleListListener
{
public void receive( List<Complex> samples );
}

View File

@@ -0,0 +1,6 @@
package io.github.dsheirer.sample.complex;
public interface ComplexSampleListener
{
public void receive( float i, float q );
}

View File

@@ -0,0 +1,49 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
*
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.complex;
public class ComplexSampleUtils
{
public static Complex multiply( Complex a,
Complex b )
{
return new Complex(
( a.inphase() * b.inphase() ) - ( a.quadrature() * b.quadrature() ),
( ( a.quadrature() * b.inphase() ) + ( a.inphase() * b.quadrature() ) ) );
}
public static Complex minus( Complex a, Complex b )
{
return new Complex( a.inphase() - b.inphase(),
a.quadrature() - b.quadrature() );
}
public static double magnitude( Complex sample )
{
return Math.sqrt( magnitudeSquared( sample ) );
}
public static int magnitudeSquared( Complex sample )
{
return (int)( ( sample.inphase() * sample.inphase() ) +
( sample.quadrature() * sample.quadrature() ) );
}
}

View File

@@ -0,0 +1,81 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2015 Dennis Sheirer
*
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Listener;
import org.apache.commons.lang3.Validate;
/**
* Assembles complex float samples into a ComplexBuffer containing an array of floats
*/
public class ComplexToComplexBufferAssembler implements ComplexSampleListener
{
private int mBufferSize;
private float[] mBuffer;
private int mBufferPointer;
private Listener<ComplexBuffer> mListener;
public ComplexToComplexBufferAssembler( int bufferSize )
{
Validate.isTrue(bufferSize % 2 == 0);
mBufferSize = bufferSize;
mBuffer = new float[ mBufferSize ];
}
public void dispose()
{
mListener = null;
mBuffer = null;
}
public void reset()
{
mBuffer = new float[ mBufferSize ];
mBufferPointer = 0;
}
@Override
public void receive( float i, float q )
{
if( mBufferPointer >= mBufferSize )
{
if( mListener != null )
{
mListener.receive( new ComplexBuffer( mBuffer ) );
}
mBuffer = new float[ mBufferSize ];
mBufferPointer = 0;
}
mBuffer[ mBufferPointer ] = i;
mBufferPointer++;
mBuffer[ mBufferPointer ] = q;
mBufferPointer++;
}
public void setListener( Listener<ComplexBuffer> listener )
{
mListener = listener;
}
}

View File

@@ -0,0 +1,8 @@
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Listener;
public interface IComplexBufferListener
{
public Listener<ComplexBuffer> getComplexBufferListener();
}

View File

@@ -0,0 +1,55 @@
package io.github.dsheirer.sample.complex;
import io.github.dsheirer.sample.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RateCounter_CB implements Listener<ComplexBuffer>
{
private final static Logger mLog =
LoggerFactory.getLogger( RateCounter_CB.class );
private Listener<ComplexBuffer> mListener;
private long mCount;
private long mStartTime = -1;
private String mName;
public RateCounter_CB()
{
mName = "UNNAMED";
}
public RateCounter_CB( String name )
{
mName = name;
}
@Override
public void receive( ComplexBuffer buffer )
{
if( mStartTime == -1 )
{
mStartTime = System.currentTimeMillis();
}
mCount += ( buffer.getSamples().length / 2 );
long elapsed = System.currentTimeMillis() - mStartTime;
if( elapsed != 0 )
{
mLog.debug( "[" + mName + "] Sample Rate: " + ( mCount / elapsed ) + " kHz" );
}
if( mListener != null )
{
mListener.receive( buffer );
}
}
public void setListener( Listener<ComplexBuffer> listener )
{
mListener = listener;
}
}

View File

@@ -0,0 +1,33 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
*
* 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 <http://www.gnu.org/licenses/>
******************************************************************************/
package io.github.dsheirer.sample.complex;
/**
* Poison Pill class to kill a processing thread. Where a thread accepts
* ComplexSample objects, send this class to the thread as a sentinal value
* to kill the processing thread.
*/
public class ThreadKiller extends Complex
{
private static final long serialVersionUID = 1L;
public ThreadKiller()
{
super( 0, 0 );
}
}