#30 - changes audio broadcaster to send full/complete MP3 frames instead of partial frames in order to reduce remote server disconnnects due to MP3 frame sync loss on remote server.

This commit is contained in:
Denny
2016-12-29 08:20:10 -05:00
parent a4e3c53ba8
commit e71a1dbeda
3 changed files with 40 additions and 23 deletions

View File

@@ -265,7 +265,7 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
{
if(mBroadcastState != state)
{
mLog.info("[" + getStreamName() + "] changing state to: " + state);
mLog.info("[" + getStreamName() + "] state: " + state);
mBroadcastState = state;
broadcast(new BroadcastEvent(this, BroadcastEvent.Event.BROADCASTER_STATE_CHANGE));
@@ -332,8 +332,9 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
{
private AtomicBoolean mProcessing = new AtomicBoolean();
private ByteArrayInputStream mInputStream;
private int mAverageBytesPerInterval;
private long mFinalSilencePadding = 0;
private int mBytesStreamedActual = 0;
private int mBytesStreamedRequired = 0;
@Override
public void run()
@@ -353,13 +354,20 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
if(mInputStream != null)
{
int length = Math.min(mAverageBytesPerInterval, mInputStream.available());
//We need to stream at 13.888 fps (144 byte frame) to achieve 2000 Bps or 16 kbps
mBytesStreamedRequired += 2000; //2000 bytes per second for 16 kbps data rate
int bytesToStream = mBytesStreamedRequired - mBytesStreamedActual;
//Trim length to whole-frame intervals (144 byte frame)
bytesToStream -= (bytesToStream % 144);
int length = Math.min(bytesToStream, mInputStream.available());
byte[] audio = new byte[length];
try
{
mInputStream.read(audio);
mBytesStreamedActual += mInputStream.read(audio);
broadcastAudio(audio);
}
@@ -382,6 +390,9 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
*/
private void nextRecording()
{
mBytesStreamedActual = 0;
mBytesStreamedRequired = 0;
boolean metadataUpdateRequired = false;
if(mInputStream != null)
@@ -408,15 +419,13 @@ public abstract class AudioBroadcaster implements IAudioPacketListener
{
mInputStream = new ByteArrayInputStream(audio);
double intervals = (double)recording.getRecordingLength() / (double)PROCESSOR_RUN_INTERVAL_MS;
mFinalSilencePadding = PROCESSOR_RUN_INTERVAL_MS -
(recording.getRecordingLength() % PROCESSOR_RUN_INTERVAL_MS);
mAverageBytesPerInterval = (int)((double)mInputStream.available() / intervals);
int wholeIntervals = (int)Math.floor(intervals) + 1;
//Silence padding to transmit at the end to keep stream length at multiples of run interval
mFinalSilencePadding = (wholeIntervals * PROCESSOR_RUN_INTERVAL_MS) -
recording.getRecordingLength();
while(mFinalSilencePadding >= PROCESSOR_RUN_INTERVAL_MS)
{
mFinalSilencePadding -= PROCESSOR_RUN_INTERVAL_MS;
}
if(connected())
{

View File

@@ -248,7 +248,6 @@ public class ShoutcastV1AudioBroadcaster extends ShoutcastAudioBroadcaster
@Override
public void messageReceived(IoSession session, Object object) throws Exception
{
mLog.debug("Message Received:" + object.toString());
if(object instanceof String)
{
String message = (String)object;

View File

@@ -57,18 +57,27 @@ public class MP3SilenceGenerator implements ISilenceGenerator
{
mLog.debug("Starting ...");
MP3SilenceGenerator generator = new MP3SilenceGenerator();
// MP3SilenceGenerator generator = new MP3SilenceGenerator();
//
// int sampleCount = 0;
//
// int block = 1;
//
// for(long x = 0; x < 5000; x ++)
// {
// byte[] silence = generator.generate(block);
//
// sampleCount += block;
//
// if(silence.length > 0)
// {
// mLog.debug("Silence:" + x + " Count:" + sampleCount + " Length:" + silence.length);
// }
// }
int sampleCount = 0;
int block = 1;
for(long x = 0; x < 500; x ++)
for(int x = 1; x <= 288; x++)
{
byte[] silence = generator.generate(block);
sampleCount += block;
mLog.debug("Silence:" + x + " Count:" + sampleCount + " Length:" + silence.length);
mLog.debug(x + ": " + (x / 144));
}
mLog.debug("Finished");