mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
controllers manager sample buffer processing and channel management. General cleanup across all modules to remove the executor from each of the start() methods. Removed the B100 tuner class since it's not yet implemented.
308 lines
7.3 KiB
Java
308 lines
7.3 KiB
Java
/*******************************************************************************
|
|
* SDR Trunk
|
|
* Copyright (C) 2014,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 source.wave;
|
|
|
|
import source.heartbeat.Heartbeat;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import sample.ConversionUtils;
|
|
import sample.Listener;
|
|
import sample.real.RealBuffer;
|
|
import source.IControllableFileSource;
|
|
import source.IFrameLocationListener;
|
|
import source.RealSource;
|
|
import source.SourceEvent;
|
|
|
|
import javax.sound.sampled.AudioFormat;
|
|
import javax.sound.sampled.AudioInputStream;
|
|
import javax.sound.sampled.AudioSystem;
|
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.Arrays;
|
|
import java.util.concurrent.ScheduledExecutorService;
|
|
|
|
public class RealWaveSource extends RealSource implements IControllableFileSource, AutoCloseable
|
|
{
|
|
private final static Logger mLog = LoggerFactory.getLogger(RealWaveSource.class);
|
|
|
|
private IFrameLocationListener mFrameLocationListener;
|
|
private int mBytesPerFrame;
|
|
private int mFrameCounter = 0;
|
|
private long mFrequency = 0;
|
|
private Listener<RealBuffer> mListener;
|
|
private AudioInputStream mInputStream;
|
|
private File mFile;
|
|
|
|
public RealWaveSource(File file) throws IOException
|
|
{
|
|
mFile = file;
|
|
}
|
|
|
|
@Override
|
|
public void setSourceEventListener(Listener<SourceEvent> listener)
|
|
{
|
|
//Not implemented
|
|
}
|
|
|
|
@Override
|
|
public void removeSourceEventListener()
|
|
{
|
|
//Not implemented
|
|
}
|
|
|
|
@Override
|
|
public Listener<SourceEvent> getSourceEventListener()
|
|
{
|
|
//Not implemented
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Not implemented
|
|
*/
|
|
@Override
|
|
public void setHeartbeatListener(Listener<Heartbeat> listener)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Not implemented
|
|
*/
|
|
@Override
|
|
public void removeHeartbeatListener()
|
|
{
|
|
}
|
|
|
|
|
|
@Override
|
|
public void reset()
|
|
{
|
|
stop();
|
|
start(null);
|
|
}
|
|
|
|
|
|
@Override
|
|
public void start(ScheduledExecutorService executor)
|
|
{
|
|
try
|
|
{
|
|
open();
|
|
}
|
|
catch(IOException | UnsupportedAudioFileException e)
|
|
{
|
|
mLog.error("Error starting real wave source", e);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
public void stop()
|
|
{
|
|
try
|
|
{
|
|
close();
|
|
}
|
|
catch(IOException e)
|
|
{
|
|
mLog.error("Error stopping real wave source", e);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
public long getFrameCount() throws IOException
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public int getSampleRate()
|
|
{
|
|
if(mInputStream != null)
|
|
{
|
|
return (int)mInputStream.getFormat().getSampleRate();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the frequency set for this file. Normally returns zero, but
|
|
* the value can be set with setFrequency() method.
|
|
*/
|
|
public long getFrequency()
|
|
{
|
|
return mFrequency;
|
|
}
|
|
|
|
/**
|
|
* Changes the value returned from getFrequency() for this source.
|
|
*/
|
|
public void setFrequency(long frequency)
|
|
{
|
|
mFrequency = frequency;
|
|
}
|
|
|
|
/**
|
|
* Closes the source file
|
|
*/
|
|
public void close() throws IOException
|
|
{
|
|
if(mInputStream != null)
|
|
{
|
|
mInputStream.close();
|
|
}
|
|
else
|
|
{
|
|
throw new IOException("Can't close wave source - was not opened");
|
|
}
|
|
|
|
mInputStream = null;
|
|
}
|
|
|
|
/**
|
|
* Opens the source file for reading
|
|
*/
|
|
public void open() throws IOException, UnsupportedAudioFileException
|
|
{
|
|
if(mInputStream == null)
|
|
{
|
|
mInputStream = AudioSystem.getAudioInputStream(mFile);
|
|
}
|
|
else
|
|
{
|
|
throw new IOException("Can't open wave source - is already opened");
|
|
}
|
|
|
|
|
|
AudioFormat format = mInputStream.getFormat();
|
|
|
|
mBytesPerFrame = format.getFrameSize();
|
|
|
|
if(format.getChannels() != 1 || format.getSampleSizeInBits() != 16)
|
|
{
|
|
throw new IOException("Unsupported Wave Format - EXPECTED: 1 " +
|
|
"channel 16-bit samples FOUND: " +
|
|
mInputStream.getFormat().getChannels() + " channels " +
|
|
mInputStream.getFormat().getSampleSizeInBits() + "-bit samples");
|
|
}
|
|
|
|
/* Broadcast that we're at frame location 0 */
|
|
broadcast(0);
|
|
}
|
|
|
|
/**
|
|
* Reads the number of frames and sends a buffer to the listener
|
|
*/
|
|
@Override
|
|
public void next(int frames) throws IOException
|
|
{
|
|
next(frames, true);
|
|
}
|
|
|
|
/**
|
|
* Reads the number of frames and optionally sends the buffer to the listener
|
|
*/
|
|
public void next(int frames, boolean broadcast) throws IOException
|
|
{
|
|
if(mInputStream != null)
|
|
{
|
|
byte[] buffer = new byte[mBytesPerFrame * frames];
|
|
|
|
/* Fill the buffer with samples from the file */
|
|
int samplesRead = mInputStream.read(buffer);
|
|
|
|
mFrameCounter += samplesRead;
|
|
|
|
broadcast(mFrameCounter);
|
|
|
|
if(broadcast && mListener != null)
|
|
{
|
|
if(samplesRead < buffer.length)
|
|
{
|
|
if(samplesRead == -1)
|
|
{
|
|
throw new IOException("End of recording");
|
|
}
|
|
|
|
buffer = Arrays.copyOf(buffer, samplesRead);
|
|
}
|
|
|
|
float[] samples = ConversionUtils
|
|
.convertFromSigned16BitSamples(buffer);
|
|
|
|
mListener.receive(new RealBuffer(samples));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Registers the listener to receive sample buffers as they are read from
|
|
* the wave file
|
|
*/
|
|
@Override
|
|
public void setListener(Listener<RealBuffer> listener)
|
|
{
|
|
mListener = listener;
|
|
}
|
|
|
|
/**
|
|
* Unregisters the listener from receiving sample buffers
|
|
*/
|
|
public void removeListener(Listener<RealBuffer> listener)
|
|
{
|
|
mListener = null;
|
|
}
|
|
|
|
@Override
|
|
public void dispose()
|
|
{
|
|
mListener = null;
|
|
}
|
|
|
|
@Override
|
|
public File getFile()
|
|
{
|
|
return mFile;
|
|
}
|
|
|
|
private void broadcast(int byteLocation)
|
|
{
|
|
int frameLocation = (int)(byteLocation / mBytesPerFrame);
|
|
|
|
if(mFrameLocationListener != null)
|
|
{
|
|
mFrameLocationListener.frameLocationUpdated(frameLocation);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setListener(IFrameLocationListener listener)
|
|
{
|
|
mFrameLocationListener = listener;
|
|
}
|
|
|
|
@Override
|
|
public void removeListener(IFrameLocationListener listener)
|
|
{
|
|
mFrameLocationListener = null;
|
|
}
|
|
}
|