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,252 @@
/*******************************************************************************
* 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.source.mixer;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.adapter.ISampleAdapter;
import io.github.dsheirer.sample.complex.ComplexBuffer;
import io.github.dsheirer.source.SourceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import java.util.concurrent.atomic.AtomicBoolean;
public class ComplexMixer
{
private final static Logger mLog =
LoggerFactory.getLogger( ComplexMixer.class );
private long mFrequency = 0;
private int mBufferSize = 16384;
private BufferReader mBufferReader = new BufferReader();
private TargetDataLine mTargetDataLine;
private AudioFormat mAudioFormat;
private String mName;
private int mBytesPerFrame = 0;
private ISampleAdapter mSampleAdapter;
private Listener<ComplexBuffer> mListener;
/**
* Complex Mixer - constructs a reader on the mixer/sound card target
* data line using the specified audio format (sample size, sample rate )
* and broadcasts complex (I/Q) sample buffers to all registered listeners.
* Reads sample buffers sized to 10% of the sample rate specified in audio
* format.
*
* @param targetDataLine - mixer or sound card to be used
*
* @param format - audio format
*
* @param name - token name to use for this mixer
*
* @param sampleAdapter - adapter to convert byte array data read from the
* mixer into ComplexBuffer. The adapter can optionally invert the channel
* data if the left/right stereo channels are inverted.
*/
public ComplexMixer( TargetDataLine targetDataLine,
AudioFormat format,
String name,
ISampleAdapter sampleAdapter,
Listener<ComplexBuffer> listener )
{
mTargetDataLine = targetDataLine;
mName = name;
mAudioFormat = format;
mSampleAdapter = sampleAdapter;
mListener = listener;
}
public TargetDataLine getTargetDataLine()
{
return mTargetDataLine;
}
public void start()
{
if( !mBufferReader.isRunning() )
{
Thread thread = new Thread( mBufferReader );
thread.setDaemon( true );
thread.setName( mName + " Complex Sample Reader" );
thread.start();
}
}
public void stop()
{
mBufferReader.stop();
}
@Override
public String toString()
{
return mName;
}
public int getSampleRate()
{
if( mTargetDataLine != null )
{
return (int)mTargetDataLine.getFormat().getSampleRate();
}
else
{
return 0;
}
}
/**
* Returns the frequency of this source. Default is 0.
*/
public long getFrequency() throws SourceException
{
return mFrequency;
}
/**
* Specify the frequency that will be returned from this source. This may
* be useful if you are streaming an external audio source in through the
* sound card and you want to specify a frequency for that source
*/
public void setFrequency( long frequency )
{
mFrequency = frequency;
}
/**
* Reader thread. Performs blocking read against the mixer target data
* line, converts the samples to an array of floats using the specified
* adapter. Dispatches float arrays to all registered listeners.
*/
public class BufferReader implements Runnable
{
private AtomicBoolean mRunning = new AtomicBoolean();
@Override
public void run()
{
if( mRunning.compareAndSet( false, true ) )
{
if( mTargetDataLine == null )
{
mRunning.set( false );
mLog.error( "ComplexMixerSource - mixer target data line"
+ " is null" );
}
else
{
mBytesPerFrame = mAudioFormat.getSampleSizeInBits() / 8;
if( mBytesPerFrame == AudioSystem.NOT_SPECIFIED )
{
mBytesPerFrame = 2;
}
/* Set buffer size to 1/10 second of samples */
mBufferSize = (int)( mAudioFormat.getSampleRate()
* 0.05 ) * mBytesPerFrame;
/* We'll reuse the same buffer for each read */
byte[] buffer = new byte[ mBufferSize ];
try
{
mTargetDataLine.open( mAudioFormat );
mTargetDataLine.start();
}
catch ( LineUnavailableException e )
{
mLog.error( "ComplexMixerSource - mixer target data line"
+ "not available to read data from", e );
mRunning.set( false );
}
while( mRunning.get() )
{
try
{
/* Blocking read - waits until the buffer fills */
mTargetDataLine.read( buffer, 0, buffer.length );
/* Convert samples to float array */
float[] samples =
mSampleAdapter.convert( buffer );
/* Dispatch samples to registered listeners */
if( mListener != null )
{
mListener.receive( new ComplexBuffer( samples ) );
}
}
catch ( Exception e )
{
mLog.error( "error while reading"
+ "from the mixer target data line", e );
mRunning.set( false );
}
}
}
/* Close the data line if it is still open */
if( mTargetDataLine != null && mTargetDataLine.isOpen() )
{
mTargetDataLine.close();
}
}
}
/**
* Stops the reader thread
*/
public void stop()
{
if( mRunning.compareAndSet( true, false ) )
{
mTargetDataLine.stop();
mTargetDataLine.close();
}
}
/**
* Indicates if the reader thread is running
*/
public boolean isRunning()
{
return mRunning.get();
}
}
public void dispose()
{
if( mBufferReader != null )
{
mBufferReader.stop();
}
mListener = null;
}
}