Merge pull request #7 from brarcher/improve-audio

Improve audio
This commit is contained in:
brarcher
2016-01-01 02:30:27 -05:00
4 changed files with 45 additions and 118 deletions

View File

@@ -1,67 +0,0 @@
/**
* This file is part of the Protect Baby Monitor.
*
* Protect Baby Monitor 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.
*
* Protect Baby Monitor 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 Protect Baby Monitor. If not, see <http://www.gnu.org/licenses/>.
*/
package protect.babymonitor;
import java.util.concurrent.BlockingQueue;
import android.media.AudioTrack;
import android.util.Log;
public class AudioPlayer implements Runnable
{
final String TAG = "BabyMonitor";
private final AudioTrack _audioTrack;
private final BlockingQueue<byte[]> _queue;
public AudioPlayer(AudioTrack audioTrack, BlockingQueue<byte[]> queue)
{
_audioTrack = audioTrack;
_queue = queue;
}
@Override
public void run()
{
Log.i(TAG, "Audio player thread started");
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
_audioTrack.play();
try
{
while(Thread.currentThread().isInterrupted() == false)
{
byte [] data = _queue.take();
int written = _audioTrack.write(data, 0, data.length);
if(written != data.length)
{
Log.i(TAG, "Did not write bytes: " + (data.length - written));
}
}
}
catch (InterruptedException e)
{
}
Log.i(TAG, "Audio player thread stopping");
_audioTrack.stop();
}
}

View File

@@ -82,9 +82,9 @@ public class DiscoverActivity extends Activity
public void onItemClick(AdapterView<?> parent, View view,
int position, long id)
{
ServiceInfoWrapper info = (ServiceInfoWrapper) parent.getItemAtPosition(position);
Intent i = new Intent(getApplicationContext(), ListenActivity.class);
Bundle b = new Bundle();
final ServiceInfoWrapper info = (ServiceInfoWrapper) parent.getItemAtPosition(position);
final Intent i = new Intent(getApplicationContext(), ListenActivity.class);
final Bundle b = new Bundle();
b.putString("address", info.getAddress());
b.putInt("port", info.getPort());
b.putString("name", info.getName());
@@ -206,8 +206,13 @@ class ServiceInfoWrapper
// If there is more than one service on the network, it will
// have a number at the end, but will appear as the following:
// "ProtectBabyMonitor\\032(number)
// Replace \\032 with a ""
return _info.getServiceName().replace("\\\\032", " ");
// or
// "ProtectBabyMonitor\032(number)
// Replace \\032 and \032 with a " "
String serviceName = _info.getServiceName();
serviceName = serviceName.replace("\\\\032", " ");
serviceName = serviceName.replace("\\032", " ");
return serviceName;
}
@Override

View File

@@ -20,9 +20,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import android.app.Activity;
import android.media.AudioFormat;
@@ -42,14 +39,15 @@ public class ListenActivity extends Activity
String _name;
Thread _listenThread;
private void streamAudio(Socket socket) throws IllegalArgumentException, IllegalStateException, IOException
private void streamAudio(final Socket socket) throws IllegalArgumentException, IllegalStateException, IOException
{
Log.i(TAG, "Setting up stream");
int frequency = 11025;
int channelConfiguration = AudioFormat.CHANNEL_OUT_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioTrack.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
final int frequency = 11025;
final int channelConfiguration = AudioFormat.CHANNEL_OUT_MONO;
final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
final int bufferSize = AudioTrack.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
final int byteBufferSize = bufferSize*2;
final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
frequency,
@@ -58,50 +56,40 @@ public class ListenActivity extends Activity
bufferSize,
AudioTrack.MODE_STREAM);
final BlockingQueue<byte[]> queue = new LinkedBlockingQueue<byte[]>(1 /*max samples queued*/);
AudioPlayer audioPlayer = new AudioPlayer(audioTrack, queue);
Thread playThread = new Thread(audioPlayer);
playThread.start();
setVolumeControlStream(AudioManager.STREAM_MUSIC);
InputStream is = socket.getInputStream();
final InputStream is = socket.getInputStream();
int read = 0;
audioTrack.play();
try
{
final byte [] buffer = new byte[byteBufferSize];
while(socket.isConnected() && read != -1 && Thread.currentThread().isInterrupted() == false)
{
byte [] buffer = new byte[bufferSize*2];
read = is.read(buffer);
if(read > 0)
{
if(read < buffer.length)
audioTrack.write(buffer, 0, read);
}
}
}
finally
{
buffer = Arrays.copyOf(buffer, read);
}
try
{
queue.add(buffer);
}
catch(IllegalStateException e)
{
Log.i(TAG, "Buffer full, dropping data");
}
}
}
playThread.interrupt();
audioTrack.stop();
socket.close();
}
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle b = getIntent().getExtras();
final Bundle b = getIntent().getExtras();
_address = b.getString("address");
_port = b.getInt("port");
_name = b.getString("name");
@@ -128,7 +116,7 @@ public class ListenActivity extends Activity
{
try
{
Socket socket = new Socket(_address, _port);
final Socket socket = new Socket(_address, _port);
streamAudio(socket);
}
catch (UnknownHostException e)

View File

@@ -56,29 +56,30 @@ public class MonitorActivity extends Activity
}
});
int frequency = 11025;
int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
final int frequency = 11025;
final int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
final int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
final AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
frequency, channelConfiguration,
audioEncoding, bufferSize);
byte[] buffer = new byte[bufferSize*2];
final int byteBufferSize = bufferSize*2;
final byte[] buffer = new byte[byteBufferSize];
try
{
audioRecord.startRecording();
OutputStream out = socket.getOutputStream();
final OutputStream out = socket.getOutputStream();
socket.setSendBufferSize(bufferSize);
socket.setSendBufferSize(byteBufferSize);
Log.d(TAG, "Socket send buffer size: " + socket.getSendBufferSize());
while (socket.isConnected() && Thread.currentThread().isInterrupted() == false)
{
int read = audioRecord.read(buffer, 0, bufferSize);
final int read = audioRecord.read(buffer, 0, bufferSize);
out.write(buffer, 0, read);
}
}
@@ -113,7 +114,7 @@ public class MonitorActivity extends Activity
serverSocket = new ServerSocket(0);
// Store the chosen port.
int localPort = serverSocket.getLocalPort();
final int localPort = serverSocket.getLocalPort();
// Register the service so that parent devices can
// locate the child device
@@ -201,9 +202,9 @@ public class MonitorActivity extends Activity
return super.onOptionsItemSelected(item);
}
private void registerService(int port)
private void registerService(final int port)
{
NsdServiceInfo serviceInfo = new NsdServiceInfo();
final NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setServiceName("ProtectBabyMonitor");
serviceInfo.setServiceType("_babymonitor._tcp.");
serviceInfo.setPort(port);