mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Initial code check in continued
This commit is contained in:
83
src/record/RecordComponentEditor.java
Normal file
83
src/record/RecordComponentEditor.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*******************************************************************************
|
||||
* 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 record;
|
||||
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
import record.config.RecordConfiguration;
|
||||
import controller.channel.AbstractChannelEditor;
|
||||
import controller.channel.ChannelNode;
|
||||
|
||||
public class RecordComponentEditor extends AbstractChannelEditor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JCheckBox mAudioRecorder = new JCheckBox( "Audio" );
|
||||
private JCheckBox mBasebandRecorder = new JCheckBox( "Baseband I/Q" );
|
||||
|
||||
public RecordComponentEditor( ChannelNode channelNode )
|
||||
{
|
||||
super( channelNode );
|
||||
|
||||
add( mAudioRecorder, "span" );
|
||||
add( mBasebandRecorder, "span" );
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
RecordConfiguration config =
|
||||
getChannelNode().getChannel().getRecordConfiguration();
|
||||
|
||||
config.clearRecorders();
|
||||
|
||||
if( mAudioRecorder.isSelected() )
|
||||
{
|
||||
config.addRecorder( RecorderType.AUDIO );
|
||||
}
|
||||
|
||||
if( mBasebandRecorder.isSelected() )
|
||||
{
|
||||
config.addRecorder( RecorderType.BASEBAND );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
RecordConfiguration config =
|
||||
getChannelNode().getChannel().getRecordConfiguration();
|
||||
|
||||
mAudioRecorder.setSelected( config.getRecorders()
|
||||
.contains( RecorderType.AUDIO ) );
|
||||
|
||||
mBasebandRecorder.setSelected( config.getRecorders()
|
||||
.contains( RecorderType.BASEBAND ) );
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
52
src/record/RecordEditor.java
Normal file
52
src/record/RecordEditor.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*******************************************************************************
|
||||
* 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 record;
|
||||
|
||||
import record.config.RecordConfiguration;
|
||||
import controller.Editor;
|
||||
|
||||
public class RecordEditor extends Editor
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected RecordConfiguration mConfig;
|
||||
|
||||
public RecordEditor( RecordConfiguration config )
|
||||
{
|
||||
mConfig = config;
|
||||
}
|
||||
|
||||
public RecordConfiguration getConfig()
|
||||
{
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
60
src/record/Recorder.java
Normal file
60
src/record/Recorder.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* 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 record;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Recorder
|
||||
{
|
||||
RecorderType mRecorderType;
|
||||
|
||||
public Recorder()
|
||||
{
|
||||
}
|
||||
|
||||
public String getFileName()
|
||||
{
|
||||
return "No Recording";
|
||||
}
|
||||
|
||||
public void start() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
public void stop() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
public void pause()
|
||||
{
|
||||
}
|
||||
|
||||
public void resume()
|
||||
{
|
||||
}
|
||||
|
||||
public Recorder( RecorderType type )
|
||||
{
|
||||
mRecorderType = type;
|
||||
}
|
||||
|
||||
public RecorderType getRecorderType()
|
||||
{
|
||||
return mRecorderType;
|
||||
}
|
||||
}
|
||||
74
src/record/RecorderManager.java
Normal file
74
src/record/RecorderManager.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*******************************************************************************
|
||||
* 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 record;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import properties.SystemProperties;
|
||||
import record.config.RecordConfiguration;
|
||||
import record.wave.ComplexWaveRecorder;
|
||||
import record.wave.FloatWaveRecorder;
|
||||
import util.TimeStamp;
|
||||
import controller.channel.ProcessingChain;
|
||||
|
||||
public class RecorderManager
|
||||
{
|
||||
public static final int sSAMPLE_RATE = 48000;
|
||||
|
||||
public RecorderManager()
|
||||
{
|
||||
}
|
||||
|
||||
public List<Recorder> getRecorder( ProcessingChain channel )
|
||||
{
|
||||
/* Note: the file suffix (ie .wav) gets added by the recorder */
|
||||
|
||||
//Get the base recording filename
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( SystemProperties.getInstance()
|
||||
.getApplicationFolder( "recordings" ) );
|
||||
sb.append( File.separator );
|
||||
sb.append( TimeStamp.getTimeStamp( "_" ) );
|
||||
sb.append( "_" );
|
||||
sb.append( channel.getChannel().getName() );
|
||||
|
||||
ArrayList<Recorder> retVal = new ArrayList<Recorder>();
|
||||
|
||||
RecordConfiguration config = channel.getChannel().getRecordConfiguration();
|
||||
|
||||
for( RecorderType recorder: config.getRecorders() )
|
||||
{
|
||||
switch( recorder )
|
||||
{
|
||||
case AUDIO:
|
||||
retVal.add( new FloatWaveRecorder( sSAMPLE_RATE,
|
||||
sb.toString() + "_audio" ) );
|
||||
break;
|
||||
case BASEBAND:
|
||||
retVal.add( new ComplexWaveRecorder( sSAMPLE_RATE,
|
||||
sb.toString() + "_baseband" ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
42
src/record/RecorderType.java
Normal file
42
src/record/RecorderType.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*******************************************************************************
|
||||
* 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 record;
|
||||
|
||||
public enum RecorderType
|
||||
{
|
||||
AUDIO( "Audio (.wav)"),
|
||||
BASEBAND( "Baseband I/Q (.wav)");
|
||||
|
||||
private String mDisplayString;
|
||||
|
||||
RecorderType( String displayString )
|
||||
{
|
||||
mDisplayString = displayString;
|
||||
}
|
||||
|
||||
public String getDisplayString()
|
||||
{
|
||||
return mDisplayString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDisplayString;
|
||||
}
|
||||
}
|
||||
57
src/record/config/RecordConfiguration.java
Normal file
57
src/record/config/RecordConfiguration.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*******************************************************************************
|
||||
* 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 record.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import record.RecorderType;
|
||||
import controller.config.Configuration;
|
||||
|
||||
@XmlRootElement( name = "record_configuration" )
|
||||
public class RecordConfiguration extends Configuration
|
||||
{
|
||||
private ArrayList<RecorderType> mRecorders = new ArrayList<RecorderType>();
|
||||
|
||||
public RecordConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
@XmlElement( name = "recorder" )
|
||||
public ArrayList<RecorderType> getRecorders()
|
||||
{
|
||||
return mRecorders;
|
||||
}
|
||||
|
||||
public void setRecorders( ArrayList<RecorderType> recorders )
|
||||
{
|
||||
mRecorders = recorders;
|
||||
}
|
||||
|
||||
public void addRecorder( RecorderType recorder )
|
||||
{
|
||||
mRecorders.add( recorder );
|
||||
}
|
||||
|
||||
public void clearRecorders()
|
||||
{
|
||||
mRecorders.clear();
|
||||
}
|
||||
}
|
||||
173
src/record/wave/BooleanWaveRecorder.java
Normal file
173
src/record/wave/BooleanWaveRecorder.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/*******************************************************************************
|
||||
* 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 record.wave;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
import log.Log;
|
||||
import record.Recorder;
|
||||
import record.RecorderType;
|
||||
import sample.Listener;
|
||||
import util.waveaudio.WaveWriter;
|
||||
import buffer.FloatSampleBufferAssembler;
|
||||
|
||||
/**
|
||||
* Threaded WAVE audio recorder for recording mono short samples to a wave file
|
||||
*/
|
||||
public class BooleanWaveRecorder extends Recorder implements Listener<Boolean>
|
||||
{
|
||||
private AudioFormat mAudioFormat;
|
||||
private boolean mRunning = false;
|
||||
private boolean mPaused = false;
|
||||
private WaveWriter mWriter;
|
||||
private String mFileName;
|
||||
private BufferProcessor mBufferProcessor;
|
||||
|
||||
//Sample buffer queue ... constrained to 512 sample buffers (arbitrary size)
|
||||
private LinkedBlockingQueue<ByteBuffer> mToWriteBufferQueue =
|
||||
new LinkedBlockingQueue<ByteBuffer>( 512 );
|
||||
private FloatSampleBufferAssembler mCurrentBuffer;
|
||||
|
||||
public BooleanWaveRecorder( int sampleRate, String filename )
|
||||
{
|
||||
super( RecorderType.AUDIO );
|
||||
|
||||
mAudioFormat = new AudioFormat( sampleRate, //SampleRate
|
||||
16, //Sample Size
|
||||
1, //Channels
|
||||
true, //Signed
|
||||
false ); //Little Endian
|
||||
|
||||
mCurrentBuffer = new FloatSampleBufferAssembler( sampleRate );
|
||||
|
||||
mFileName = filename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName()
|
||||
{
|
||||
return mFileName + ".wav";
|
||||
}
|
||||
|
||||
public void start() throws IOException
|
||||
{
|
||||
if( !mRunning )
|
||||
{
|
||||
mWriter = new WaveWriter( mFileName + ".wav", mAudioFormat );
|
||||
mWriter.start();
|
||||
|
||||
mBufferProcessor = new BufferProcessor();
|
||||
mBufferProcessor.start();
|
||||
|
||||
mRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() throws IOException
|
||||
{
|
||||
if( mRunning )
|
||||
{
|
||||
mBufferProcessor = null;
|
||||
|
||||
mWriter.stop();
|
||||
mWriter = null;
|
||||
|
||||
mRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void pause()
|
||||
{
|
||||
mPaused = true;
|
||||
}
|
||||
|
||||
public void resume()
|
||||
{
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes that the byte[] represents samples corresponding to the
|
||||
* audio format object defined at construction
|
||||
*/
|
||||
public void receive( ByteBuffer buffer )
|
||||
{
|
||||
if( mRunning && !mPaused )
|
||||
{
|
||||
boolean success = mToWriteBufferQueue.offer( buffer );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
Log.error( "Wave recorder buffer overflow - throwing away " + buffer.capacity() + " samples" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Boolean sample )
|
||||
{
|
||||
/**
|
||||
* If the sample is true, put short value of 5000, otherwise
|
||||
* put a short value of -5000
|
||||
*/
|
||||
mCurrentBuffer.put( sample ? 5000 : (short)-5000 );
|
||||
|
||||
if( !mCurrentBuffer.hasRemaining() )
|
||||
{
|
||||
//Dispatch the buffer to be written to disk
|
||||
if( !mToWriteBufferQueue.offer( mCurrentBuffer.get() ) )
|
||||
{
|
||||
//We had an overflow ... log it
|
||||
Log.error( "ShortWaveRecorder: buffer overflow - throwing away 1 second of sample data" );
|
||||
}
|
||||
|
||||
mCurrentBuffer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public class BufferProcessor extends Thread
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( mWriter != null )
|
||||
{
|
||||
mWriter.write( mToWriteBufferQueue.take() );
|
||||
}
|
||||
}
|
||||
catch ( IOException ioe )
|
||||
{
|
||||
Log.error( "IOException while trying to write to the wave writer - " + ioe.getLocalizedMessage() );
|
||||
}
|
||||
catch ( InterruptedException e )
|
||||
{
|
||||
Log.error( "Oops ... error while processing the buffer queue for " +
|
||||
" the wave recorder - " + e.getLocalizedMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
175
src/record/wave/ComplexWaveRecorder.java
Normal file
175
src/record/wave/ComplexWaveRecorder.java
Normal file
@@ -0,0 +1,175 @@
|
||||
/*******************************************************************************
|
||||
* 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 record.wave;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
import log.Log;
|
||||
import record.Recorder;
|
||||
import record.RecorderType;
|
||||
import sample.Listener;
|
||||
import sample.complex.ComplexSample;
|
||||
import util.waveaudio.WaveWriter;
|
||||
import buffer.ComplexSampleBufferAssembler;
|
||||
|
||||
/**
|
||||
* Threaded WAVE audio recorder for recording complex (I&Q) samples to a wave
|
||||
* file
|
||||
*/
|
||||
public class ComplexWaveRecorder extends Recorder implements Listener<ComplexSample>
|
||||
{
|
||||
private AudioFormat mAudioFormat;
|
||||
private boolean mRunning = false;
|
||||
private boolean mPaused = false;
|
||||
private WaveWriter mWriter;
|
||||
private String mFileName;
|
||||
private BufferProcessor mBufferProcessor;
|
||||
|
||||
//Sample buffer queue ... constrained to 512 sample buffers (arbitrary size)
|
||||
private LinkedBlockingQueue<ByteBuffer> mToWriteBufferQueue =
|
||||
new LinkedBlockingQueue<ByteBuffer>( 512 );
|
||||
private ComplexSampleBufferAssembler mCurrentBuffer;
|
||||
|
||||
public ComplexWaveRecorder( int sampleRate, String filename )
|
||||
{
|
||||
super( RecorderType.AUDIO );
|
||||
|
||||
mAudioFormat = new AudioFormat( sampleRate, //SampleRate
|
||||
16, //Sample Size
|
||||
2, //Channels
|
||||
true, //Signed
|
||||
false ); //Little Endian
|
||||
|
||||
mCurrentBuffer = new ComplexSampleBufferAssembler( sampleRate );
|
||||
|
||||
mFileName = filename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName()
|
||||
{
|
||||
return mFileName + ".wav";
|
||||
}
|
||||
|
||||
public void start() throws IOException
|
||||
{
|
||||
if( !mRunning )
|
||||
{
|
||||
mWriter = new WaveWriter( mFileName + ".wav", mAudioFormat );
|
||||
mWriter.start();
|
||||
|
||||
mBufferProcessor = new BufferProcessor();
|
||||
mBufferProcessor.start();
|
||||
|
||||
mRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() throws IOException
|
||||
{
|
||||
if( mRunning )
|
||||
{
|
||||
mBufferProcessor = null;
|
||||
|
||||
mWriter.stop();
|
||||
mWriter = null;
|
||||
|
||||
mRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void pause()
|
||||
{
|
||||
mPaused = true;
|
||||
}
|
||||
|
||||
public void resume()
|
||||
{
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes that the byte[] represents samples corresponding to the
|
||||
* audio format object defined at construction
|
||||
*/
|
||||
public void receive( ByteBuffer buffer )
|
||||
{
|
||||
if( mRunning && !mPaused )
|
||||
{
|
||||
boolean success = mToWriteBufferQueue.offer( buffer );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
Log.error( "Wave recorder buffer overflow - throwing away " +
|
||||
buffer.capacity() + " samples" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( ComplexSample sample )
|
||||
{
|
||||
mCurrentBuffer.put( sample );
|
||||
|
||||
if( !mCurrentBuffer.hasRemaining() )
|
||||
{
|
||||
//Dispatch the buffer to be written to disk
|
||||
if( !mToWriteBufferQueue.offer( mCurrentBuffer.get() ) )
|
||||
{
|
||||
//We had an overflow ... log it
|
||||
Log.error( "ComplexWaveRecorder: buffer overflow - throwing "
|
||||
+ "away 1 second of sample data" );
|
||||
}
|
||||
|
||||
mCurrentBuffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public class BufferProcessor extends Thread
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( mWriter != null )
|
||||
{
|
||||
mWriter.write( mToWriteBufferQueue.take() );
|
||||
}
|
||||
}
|
||||
catch ( IOException ioe )
|
||||
{
|
||||
Log.error( "IOException while trying to write to the wave "
|
||||
+ "writer - " + ioe.getLocalizedMessage() );
|
||||
}
|
||||
catch ( InterruptedException e )
|
||||
{
|
||||
Log.error( "Oops ... error while processing the buffer "
|
||||
+ "queue for the wave recorder - " +
|
||||
e.getLocalizedMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
173
src/record/wave/FloatWaveRecorder.java
Normal file
173
src/record/wave/FloatWaveRecorder.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/*******************************************************************************
|
||||
* 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 record.wave;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
import log.Log;
|
||||
import record.Recorder;
|
||||
import record.RecorderType;
|
||||
import sample.Listener;
|
||||
import util.waveaudio.WaveWriter;
|
||||
import buffer.FloatSampleBufferAssembler;
|
||||
|
||||
/**
|
||||
* Threaded WAVE audio recorder for recording mono float samples to a wave file
|
||||
*/
|
||||
public class FloatWaveRecorder extends Recorder implements Listener<Float>
|
||||
{
|
||||
private AudioFormat mAudioFormat;
|
||||
private boolean mRunning = false;
|
||||
private boolean mPaused = false;
|
||||
private WaveWriter mWriter;
|
||||
private String mFileName;
|
||||
private BufferProcessor mBufferProcessor;
|
||||
|
||||
//Sample buffer queue ... constrained to 512 sample buffers (arbitrary size)
|
||||
private LinkedBlockingQueue<ByteBuffer> mToWriteBufferQueue =
|
||||
new LinkedBlockingQueue<ByteBuffer>( 512 );
|
||||
private FloatSampleBufferAssembler mCurrentBuffer;
|
||||
|
||||
public FloatWaveRecorder( int sampleRate, String filename )
|
||||
{
|
||||
super( RecorderType.AUDIO );
|
||||
|
||||
mAudioFormat = new AudioFormat( sampleRate, //SampleRate
|
||||
16, //Sample Size
|
||||
1, //Channels
|
||||
true, //Signed
|
||||
false ); //Little Endian
|
||||
|
||||
mCurrentBuffer = new FloatSampleBufferAssembler( sampleRate );
|
||||
|
||||
mFileName = filename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName()
|
||||
{
|
||||
return mFileName + ".wav";
|
||||
}
|
||||
|
||||
public void start() throws IOException
|
||||
{
|
||||
if( !mRunning )
|
||||
{
|
||||
mWriter = new WaveWriter( mFileName + ".wav", mAudioFormat );
|
||||
mWriter.start();
|
||||
|
||||
mBufferProcessor = new BufferProcessor();
|
||||
mBufferProcessor.start();
|
||||
|
||||
mRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() throws IOException
|
||||
{
|
||||
if( mRunning )
|
||||
{
|
||||
mBufferProcessor = null;
|
||||
|
||||
mWriter.stop();
|
||||
mWriter = null;
|
||||
|
||||
mRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void pause()
|
||||
{
|
||||
mPaused = true;
|
||||
}
|
||||
|
||||
public void resume()
|
||||
{
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes that the byte[] represents samples corresponding to the
|
||||
* audio format object defined at construction
|
||||
*/
|
||||
public void receive( ByteBuffer buffer )
|
||||
{
|
||||
if( mRunning && !mPaused )
|
||||
{
|
||||
boolean success = mToWriteBufferQueue.offer( buffer );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
Log.error( "Wave recorder buffer overflow - throwing away " +
|
||||
buffer.capacity() + " samples" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( Float sample )
|
||||
{
|
||||
mCurrentBuffer.put( sample );
|
||||
|
||||
if( !mCurrentBuffer.hasRemaining() )
|
||||
{
|
||||
//Dispatch the buffer to be written to disk
|
||||
if( !mToWriteBufferQueue.offer( mCurrentBuffer.get() ) )
|
||||
{
|
||||
//We had an overflow ... log it
|
||||
Log.error( "FloatWaveRecorder: buffer overflow - throwing "
|
||||
+ "away 1 second of sample data" );
|
||||
}
|
||||
|
||||
mCurrentBuffer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public class BufferProcessor extends Thread
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( mWriter != null )
|
||||
{
|
||||
mWriter.write( mToWriteBufferQueue.take() );
|
||||
}
|
||||
}
|
||||
catch ( IOException ioe )
|
||||
{
|
||||
Log.error( "IOException while trying to write to the wave "
|
||||
+ "writer - " + ioe.getLocalizedMessage() );
|
||||
}
|
||||
catch ( InterruptedException e )
|
||||
{
|
||||
Log.error( "Oops ... error while processing the buffer "
|
||||
+ "queue for the wave recorder - " +
|
||||
e.getLocalizedMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
134
src/record/wave/WaveRecorder.java
Normal file
134
src/record/wave/WaveRecorder.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*******************************************************************************
|
||||
* 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 record.wave;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
|
||||
import log.Log;
|
||||
import record.Recorder;
|
||||
import record.RecorderType;
|
||||
import util.waveaudio.WaveWriter;
|
||||
|
||||
/**
|
||||
* Threaded WAVE audio recorder.
|
||||
*/
|
||||
public class WaveRecorder extends Recorder
|
||||
{
|
||||
private AudioFormat mAudioFormat;
|
||||
private boolean mRunning = false;
|
||||
private boolean mPaused = false;
|
||||
private WaveWriter mWriter;
|
||||
private String mFileName;
|
||||
private BufferProcessor mBufferProcessor;
|
||||
|
||||
//Sample buffer queue ... constrained to 512 sample buffers (arbitrary size)
|
||||
LinkedBlockingQueue<ByteBuffer> mBufferQueue =
|
||||
new LinkedBlockingQueue<ByteBuffer>( 512 );
|
||||
|
||||
public WaveRecorder( AudioFormat format, String filename )
|
||||
{
|
||||
super( RecorderType.AUDIO );
|
||||
|
||||
mAudioFormat = format;
|
||||
mFileName = filename;
|
||||
}
|
||||
|
||||
public void start() throws IOException
|
||||
{
|
||||
if( !mRunning )
|
||||
{
|
||||
mWriter = new WaveWriter( mFileName + ".wav", mAudioFormat );
|
||||
mWriter.start();
|
||||
|
||||
mBufferProcessor = new BufferProcessor();
|
||||
mBufferProcessor.start();
|
||||
|
||||
mRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() throws IOException
|
||||
{
|
||||
if( mRunning )
|
||||
{
|
||||
mBufferProcessor = null;
|
||||
|
||||
mWriter.stop();
|
||||
mWriter = null;
|
||||
|
||||
mRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void pause()
|
||||
{
|
||||
mPaused = true;
|
||||
}
|
||||
|
||||
public void resume()
|
||||
{
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes that the byte[] represents samples corresponding to the
|
||||
* audio format object defined at construction
|
||||
*/
|
||||
public void receive( ByteBuffer buffer )
|
||||
{
|
||||
if( mRunning && !mPaused )
|
||||
{
|
||||
boolean success = mBufferQueue.offer( buffer );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
Log.error( "Wave recorder buffer overflow - throwing away " + buffer.capacity() + " samples" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BufferProcessor extends Thread
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( mWriter != null )
|
||||
{
|
||||
mWriter.write( mBufferQueue.take() );
|
||||
}
|
||||
}
|
||||
catch ( IOException ioe )
|
||||
{
|
||||
Log.error( "IOException while trying to write to the wave writer - " + ioe.getLocalizedMessage() );
|
||||
}
|
||||
catch ( InterruptedException e )
|
||||
{
|
||||
Log.error( "Oops ... error while processing the buffer queue for " +
|
||||
" the wave recorder - " + e.getLocalizedMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/record/wave/WriteExample.java
Normal file
72
src/record/wave/WriteExample.java
Normal 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 record.wave;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import util.waveaudio.WavFile;
|
||||
|
||||
|
||||
public class WriteExample
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
int sampleRate = 44100; // Samples per second
|
||||
double duration = 5.0; // Seconds
|
||||
|
||||
// Calculate the number of frames required for specified duration
|
||||
long numFrames = (long)(duration * sampleRate);
|
||||
|
||||
// Create a wav file with the name specified as the first argument
|
||||
WavFile wavFile = WavFile.newWavFile(new File(args[0]), 2, numFrames, 16, sampleRate);
|
||||
|
||||
// Create a buffer of 100 frames
|
||||
double[][] buffer = new double[2][100];
|
||||
|
||||
// Initialise a local frame counter
|
||||
long frameCounter = 0;
|
||||
|
||||
// Loop until all frames written
|
||||
while (frameCounter < numFrames)
|
||||
{
|
||||
// Determine how many frames to write, up to a maximum of the buffer size
|
||||
long remaining = wavFile.getFramesRemaining();
|
||||
int toWrite = (remaining > 100) ? 100 : (int) remaining;
|
||||
|
||||
// Fill the buffer, one tone per channel
|
||||
for (int s=0 ; s<toWrite ; s++, frameCounter++)
|
||||
{
|
||||
buffer[0][s] = Math.sin(2.0 * Math.PI * 400 * frameCounter / sampleRate);
|
||||
buffer[1][s] = Math.sin(2.0 * Math.PI * 500 * frameCounter / sampleRate);
|
||||
}
|
||||
|
||||
// Write the buffer
|
||||
wavFile.writeFrames(buffer, toWrite);
|
||||
}
|
||||
|
||||
// Close the wavFile
|
||||
wavFile.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user