mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-15 01:57:39 -05:00
#1170 resolves issue with MP3 encoded audio raspy. Adds auto-clipping of PCM audio prior to encoding and adds 4x new 32-bit input sample rate selections to choose from, in addition to original 4x 16-bit input formats. (#1171)
Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
@@ -71,7 +71,7 @@ public class BeepAction extends RecurringAction
|
|||||||
@Override
|
@Override
|
||||||
public void performAction(Alias alias, IMessage message )
|
public void performAction(Alias alias, IMessage message )
|
||||||
{
|
{
|
||||||
DataLine.Info info = new DataLine.Info(Clip.class, AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO);
|
DataLine.Info info = new DataLine.Info(Clip.class, AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO);
|
||||||
|
|
||||||
if(!AudioSystem.isLineSupported(info))
|
if(!AudioSystem.isLineSupported(info))
|
||||||
{
|
{
|
||||||
@@ -82,7 +82,7 @@ public class BeepAction extends RecurringAction
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Clip clip = (Clip)AudioSystem.getLine(info);
|
Clip clip = (Clip)AudioSystem.getLine(info);
|
||||||
clip.open(AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO, mToneBytes, 0, mToneBytes.length);
|
clip.open(AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO, mToneBytes, 0, mToneBytes.length);
|
||||||
clip.start();
|
clip.start();
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
|||||||
@@ -24,112 +24,107 @@ import javax.sound.sampled.DataLine;
|
|||||||
import javax.sound.sampled.Line;
|
import javax.sound.sampled.Line;
|
||||||
import javax.sound.sampled.SourceDataLine;
|
import javax.sound.sampled.SourceDataLine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audio formats
|
||||||
|
*/
|
||||||
public class AudioFormats
|
public class AudioFormats
|
||||||
{
|
{
|
||||||
public static final AudioFormat.Encoding IMBE_ENCODING =
|
|
||||||
new AudioFormat.Encoding( "IMBE" );
|
|
||||||
|
|
||||||
public static final boolean LITTLE_ENDIAN = false;
|
public static final boolean LITTLE_ENDIAN = false;
|
||||||
public static final boolean BIG_ENDIAN = true;
|
|
||||||
|
|
||||||
public static final float IMBE_FRAME_RATE = 50;
|
|
||||||
public static final float IMBE_SAMPLE_RATE = 50;
|
|
||||||
|
|
||||||
public static final float PCM_8_KHZ_RATE = 8000;
|
public static final float PCM_8_KHZ_RATE = 8000;
|
||||||
public static final float PCM_16_KHZ_RATE = 16000;
|
public static final float PCM_16_KHZ_RATE = 16000;
|
||||||
public static final float PCM_22050_HZ_RATE = 22050;
|
public static final float PCM_22050_HZ_RATE = 22050;
|
||||||
public static final float PCM_44100_HZ_RATE = 44100;
|
public static final float PCM_44100_HZ_RATE = 44100;
|
||||||
public static final float PCM_48_KHZ_RATE = 48000;
|
|
||||||
|
|
||||||
public static final int IMBE_FRAME_SIZE_BYTES = 18;
|
|
||||||
public static final int IMBE_SAMPLE_SIZE_BITS = 144;
|
|
||||||
public static final int ONE_CHANNEL = 1;
|
public static final int ONE_CHANNEL = 1;
|
||||||
public static final int TWO_CHANNELS = 2;
|
public static final int TWO_CHANNELS = 2;
|
||||||
public static final int PCM_SAMPLE_SIZE_BITS = 16;
|
public static final int PCM_SAMPLE_SIZE_16_BITS = 16;
|
||||||
public static final int PCM_FRAME_SIZE_BYTES_MONO = 2;
|
public static final int PCM_SAMPLE_SIZE_32_BITS = 32;
|
||||||
public static final int PCM_FRAME_SIZE_BYTES_STEREO = 4;
|
public static final int PCM_FRAME_SIZE_BYTES_16_BIT_MONO = 2;
|
||||||
|
public static final int PCM_FRAME_SIZE_BYTES_32_BIT_MONO = 4;
|
||||||
public static AudioFormat IMBE_AUDIO_FORMAT =
|
public static final int PCM_FRAME_SIZE_BYTES_16_BIT_STEREO = 4;
|
||||||
new AudioFormat( IMBE_ENCODING,
|
|
||||||
IMBE_SAMPLE_RATE,
|
|
||||||
IMBE_SAMPLE_SIZE_BITS,
|
|
||||||
ONE_CHANNEL,
|
|
||||||
IMBE_FRAME_SIZE_BYTES,
|
|
||||||
IMBE_FRAME_RATE,
|
|
||||||
LITTLE_ENDIAN );
|
|
||||||
|
|
||||||
public static AudioFormat PCM_SIGNED_8_KHZ_16BITS_MONO =
|
|
||||||
new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
|
||||||
PCM_8_KHZ_RATE,
|
|
||||||
PCM_SAMPLE_SIZE_BITS,
|
|
||||||
ONE_CHANNEL,
|
|
||||||
PCM_FRAME_SIZE_BYTES_MONO,
|
|
||||||
PCM_8_KHZ_RATE,
|
|
||||||
LITTLE_ENDIAN );
|
|
||||||
|
|
||||||
public static AudioFormat PCM_SIGNED_16_KHZ_16BITS_MONO =
|
public static AudioFormat PCM_SIGNED_8000_HZ_32_BIT_MONO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
|
||||||
PCM_16_KHZ_RATE,
|
|
||||||
PCM_SAMPLE_SIZE_BITS,
|
|
||||||
ONE_CHANNEL,
|
|
||||||
PCM_FRAME_SIZE_BYTES_MONO,
|
|
||||||
PCM_16_KHZ_RATE,
|
|
||||||
LITTLE_ENDIAN );
|
|
||||||
|
|
||||||
public static AudioFormat PCM_SIGNED_22050_HZ_16BITS_MONO =
|
|
||||||
new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
|
||||||
PCM_22050_HZ_RATE,
|
|
||||||
PCM_SAMPLE_SIZE_BITS,
|
|
||||||
ONE_CHANNEL,
|
|
||||||
PCM_FRAME_SIZE_BYTES_MONO,
|
|
||||||
PCM_22050_HZ_RATE,
|
|
||||||
LITTLE_ENDIAN );
|
|
||||||
|
|
||||||
public static AudioFormat PCM_SIGNED_44100_HZ_16BITS_MONO =
|
|
||||||
new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
|
||||||
PCM_44100_HZ_RATE,
|
|
||||||
PCM_SAMPLE_SIZE_BITS,
|
|
||||||
ONE_CHANNEL,
|
|
||||||
PCM_FRAME_SIZE_BYTES_MONO,
|
|
||||||
PCM_44100_HZ_RATE,
|
|
||||||
LITTLE_ENDIAN );
|
|
||||||
|
|
||||||
public static AudioFormat PCM_SIGNED_8KHZ_16BITS_STEREO =
|
|
||||||
new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
|
||||||
PCM_8_KHZ_RATE,
|
PCM_8_KHZ_RATE,
|
||||||
PCM_SAMPLE_SIZE_BITS,
|
PCM_SAMPLE_SIZE_32_BITS,
|
||||||
|
ONE_CHANNEL,
|
||||||
|
PCM_FRAME_SIZE_BYTES_32_BIT_MONO,
|
||||||
|
PCM_8_KHZ_RATE,
|
||||||
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
|
public static AudioFormat PCM_SIGNED_8000_HZ_16_BIT_MONO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
PCM_8_KHZ_RATE,
|
||||||
|
PCM_SAMPLE_SIZE_16_BITS,
|
||||||
|
ONE_CHANNEL,
|
||||||
|
PCM_FRAME_SIZE_BYTES_16_BIT_MONO,
|
||||||
|
PCM_8_KHZ_RATE,
|
||||||
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
|
public static AudioFormat PCM_SIGNED_16000_HZ_16_BIT_MONO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
PCM_16_KHZ_RATE,
|
||||||
|
PCM_SAMPLE_SIZE_16_BITS,
|
||||||
|
ONE_CHANNEL,
|
||||||
|
PCM_FRAME_SIZE_BYTES_16_BIT_MONO,
|
||||||
|
PCM_16_KHZ_RATE,
|
||||||
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
|
public static AudioFormat PCM_SIGNED_16000_HZ_32_BIT_MONO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
PCM_16_KHZ_RATE,
|
||||||
|
PCM_SAMPLE_SIZE_32_BITS,
|
||||||
|
ONE_CHANNEL,
|
||||||
|
PCM_FRAME_SIZE_BYTES_32_BIT_MONO,
|
||||||
|
PCM_16_KHZ_RATE,
|
||||||
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
|
public static AudioFormat PCM_SIGNED_22050_HZ_16_BIT_MONO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
PCM_22050_HZ_RATE,
|
||||||
|
PCM_SAMPLE_SIZE_16_BITS,
|
||||||
|
ONE_CHANNEL,
|
||||||
|
PCM_FRAME_SIZE_BYTES_16_BIT_MONO,
|
||||||
|
PCM_22050_HZ_RATE,
|
||||||
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
|
public static AudioFormat PCM_SIGNED_22050_HZ_32_BIT_MONO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
PCM_22050_HZ_RATE,
|
||||||
|
PCM_SAMPLE_SIZE_32_BITS,
|
||||||
|
ONE_CHANNEL,
|
||||||
|
PCM_FRAME_SIZE_BYTES_32_BIT_MONO,
|
||||||
|
PCM_22050_HZ_RATE,
|
||||||
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
|
public static AudioFormat PCM_SIGNED_44100_HZ_16_BIT_MONO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
PCM_44100_HZ_RATE,
|
||||||
|
PCM_SAMPLE_SIZE_16_BITS,
|
||||||
|
ONE_CHANNEL,
|
||||||
|
PCM_FRAME_SIZE_BYTES_16_BIT_MONO,
|
||||||
|
PCM_44100_HZ_RATE,
|
||||||
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
|
public static AudioFormat PCM_SIGNED_44100_HZ_32_BIT_MONO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
PCM_44100_HZ_RATE,
|
||||||
|
PCM_SAMPLE_SIZE_32_BITS,
|
||||||
|
ONE_CHANNEL,
|
||||||
|
PCM_FRAME_SIZE_BYTES_32_BIT_MONO,
|
||||||
|
PCM_44100_HZ_RATE,
|
||||||
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
|
public static AudioFormat PCM_SIGNED_8000_HZ_16BITS_STEREO = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
PCM_8_KHZ_RATE,
|
||||||
|
PCM_SAMPLE_SIZE_16_BITS,
|
||||||
TWO_CHANNELS,
|
TWO_CHANNELS,
|
||||||
PCM_FRAME_SIZE_BYTES_STEREO,
|
PCM_FRAME_SIZE_BYTES_16_BIT_STEREO,
|
||||||
PCM_8_KHZ_RATE,
|
PCM_8_KHZ_RATE,
|
||||||
LITTLE_ENDIAN );
|
LITTLE_ENDIAN );
|
||||||
|
|
||||||
public static AudioFormat PCM_SIGNED_48KHZ_16BITS_MONO =
|
|
||||||
new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
|
||||||
PCM_48_KHZ_RATE,
|
|
||||||
PCM_SAMPLE_SIZE_BITS,
|
|
||||||
ONE_CHANNEL,
|
|
||||||
PCM_FRAME_SIZE_BYTES_MONO,
|
|
||||||
PCM_48_KHZ_RATE,
|
|
||||||
LITTLE_ENDIAN );
|
|
||||||
|
|
||||||
public static AudioFormat PCM_SIGNED_48KHZ_16BITS_STEREO =
|
|
||||||
new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
|
|
||||||
PCM_48_KHZ_RATE,
|
|
||||||
PCM_SAMPLE_SIZE_BITS,
|
|
||||||
TWO_CHANNELS,
|
|
||||||
PCM_FRAME_SIZE_BYTES_STEREO,
|
|
||||||
PCM_48_KHZ_RATE,
|
|
||||||
LITTLE_ENDIAN );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Source Data Line Info for a 48 kHz, 16-bits signed PCM one channel
|
* Source Data Line Info for a 48 kHz, 16-bits signed PCM one channel
|
||||||
*/
|
*/
|
||||||
public static final Line.Info MONO_SOURCE_DATALINE_INFO =
|
public static final Line.Info MONO_SOURCE_DATALINE_INFO =
|
||||||
new DataLine.Info( SourceDataLine.class, PCM_SIGNED_8_KHZ_16BITS_MONO);
|
new DataLine.Info( SourceDataLine.class, PCM_SIGNED_8000_HZ_16_BIT_MONO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Source Data Line Info for a 48 kHz, 16-bits signed PCM two channels
|
* Source Data Line Info for a 48 kHz, 16-bits signed PCM two channels
|
||||||
*/
|
*/
|
||||||
public static final Line.Info STEREO_SOURCE_DATALINE_INFO =
|
public static final Line.Info STEREO_SOURCE_DATALINE_INFO =
|
||||||
new DataLine.Info( SourceDataLine.class, PCM_SIGNED_8KHZ_16BITS_STEREO);
|
new DataLine.Info( SourceDataLine.class, PCM_SIGNED_8000_HZ_16BITS_STEREO);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.github.dsheirer.audio.broadcast;
|
package io.github.dsheirer.audio.broadcast;
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
|
||||||
import io.github.dsheirer.audio.convert.ISilenceGenerator;
|
import io.github.dsheirer.audio.convert.ISilenceGenerator;
|
||||||
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.identifier.IdentifierCollection;
|
import io.github.dsheirer.identifier.IdentifierCollection;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
@@ -73,13 +73,13 @@ public abstract class AudioStreamingBroadcaster<T extends BroadcastConfiguration
|
|||||||
* The last audio packet's metadata is automatically attached to the closed audio recording when it is enqueued for
|
* The last audio packet's metadata is automatically attached to the closed audio recording when it is enqueued for
|
||||||
* broadcast. That metadata will be updated on the remote server once the audio recording is opened for streaming.
|
* broadcast. That metadata will be updated on the remote server once the audio recording is opened for streaming.
|
||||||
*/
|
*/
|
||||||
public AudioStreamingBroadcaster(T broadcastConfiguration, AudioSampleRate audioSampleRate, MP3Setting mp3Setting)
|
public AudioStreamingBroadcaster(T broadcastConfiguration, InputAudioFormat inputAudioFormat, MP3Setting mp3Setting)
|
||||||
{
|
{
|
||||||
super(broadcastConfiguration);
|
super(broadcastConfiguration);
|
||||||
mDelay = getBroadcastConfiguration().getDelay();
|
mDelay = getBroadcastConfiguration().getDelay();
|
||||||
mMaximumRecordingAge = getBroadcastConfiguration().getMaximumRecordingAge();
|
mMaximumRecordingAge = getBroadcastConfiguration().getMaximumRecordingAge();
|
||||||
mSilenceGenerator = BroadcastFactory.getSilenceGenerator(broadcastConfiguration.getBroadcastFormat(),
|
mSilenceGenerator = BroadcastFactory.getSilenceGenerator(broadcastConfiguration.getBroadcastFormat(),
|
||||||
audioSampleRate, mp3Setting);
|
inputAudioFormat, mp3Setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose()
|
public void dispose()
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1AudioBroadcast
|
|||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1Configuration;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v1.ShoutcastV1Configuration;
|
||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2AudioStreamingBroadcaster;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2AudioStreamingBroadcaster;
|
||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2Configuration;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ShoutcastV2Configuration;
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
|
||||||
import io.github.dsheirer.audio.convert.IAudioConverter;
|
import io.github.dsheirer.audio.convert.IAudioConverter;
|
||||||
import io.github.dsheirer.audio.convert.ISilenceGenerator;
|
import io.github.dsheirer.audio.convert.ISilenceGenerator;
|
||||||
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.audio.convert.MP3SilenceGenerator;
|
import io.github.dsheirer.audio.convert.MP3SilenceGenerator;
|
||||||
@@ -55,29 +55,29 @@ public class BroadcastFactory
|
|||||||
{
|
{
|
||||||
if(configuration != null)
|
if(configuration != null)
|
||||||
{
|
{
|
||||||
AudioSampleRate audioSampleRate = userPreferences.getMP3Preference().getAudioSampleRate();
|
InputAudioFormat inputAudioFormat = userPreferences.getMP3Preference().getAudioSampleRate();
|
||||||
MP3Setting mp3Setting = userPreferences.getMP3Preference().getMP3Setting();
|
MP3Setting mp3Setting = userPreferences.getMP3Preference().getMP3Setting();
|
||||||
|
|
||||||
switch(configuration.getBroadcastServerType())
|
switch(configuration.getBroadcastServerType())
|
||||||
{
|
{
|
||||||
case BROADCASTIFY_CALL:
|
case BROADCASTIFY_CALL:
|
||||||
return new BroadcastifyCallBroadcaster((BroadcastifyCallConfiguration)configuration,
|
return new BroadcastifyCallBroadcaster((BroadcastifyCallConfiguration)configuration,
|
||||||
audioSampleRate, mp3Setting, aliasModel);
|
inputAudioFormat, mp3Setting, aliasModel);
|
||||||
case BROADCASTIFY:
|
case BROADCASTIFY:
|
||||||
return new IcecastTCPAudioBroadcaster((BroadcastifyFeedConfiguration) configuration,
|
return new IcecastTCPAudioBroadcaster((BroadcastifyFeedConfiguration) configuration,
|
||||||
audioSampleRate, mp3Setting, aliasModel);
|
inputAudioFormat, mp3Setting, aliasModel);
|
||||||
case ICECAST_TCP:
|
case ICECAST_TCP:
|
||||||
return new IcecastTCPAudioBroadcaster((IcecastTCPConfiguration) configuration, audioSampleRate,
|
return new IcecastTCPAudioBroadcaster((IcecastTCPConfiguration) configuration, inputAudioFormat,
|
||||||
mp3Setting, aliasModel);
|
mp3Setting, aliasModel);
|
||||||
case ICECAST_HTTP:
|
case ICECAST_HTTP:
|
||||||
return new IcecastHTTPAudioBroadcaster((IcecastHTTPConfiguration) configuration, audioSampleRate,
|
return new IcecastHTTPAudioBroadcaster((IcecastHTTPConfiguration) configuration, inputAudioFormat,
|
||||||
mp3Setting, aliasModel);
|
mp3Setting, aliasModel);
|
||||||
case SHOUTCAST_V1:
|
case SHOUTCAST_V1:
|
||||||
return new ShoutcastV1AudioBroadcaster((ShoutcastV1Configuration) configuration, audioSampleRate,
|
return new ShoutcastV1AudioBroadcaster((ShoutcastV1Configuration) configuration, inputAudioFormat,
|
||||||
mp3Setting, aliasModel);
|
mp3Setting, aliasModel);
|
||||||
case SHOUTCAST_V2:
|
case SHOUTCAST_V2:
|
||||||
return new ShoutcastV2AudioStreamingBroadcaster((ShoutcastV2Configuration) configuration,
|
return new ShoutcastV2AudioStreamingBroadcaster((ShoutcastV2Configuration) configuration,
|
||||||
audioSampleRate, mp3Setting, aliasModel);
|
inputAudioFormat, mp3Setting, aliasModel);
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
default:
|
default:
|
||||||
mLog.info("Unrecognized broadcastAudio configuration: " + configuration.getBroadcastFormat().name());
|
mLog.info("Unrecognized broadcastAudio configuration: " + configuration.getBroadcastFormat().name());
|
||||||
@@ -94,13 +94,13 @@ public class BroadcastFactory
|
|||||||
* @param configuration containing the requested output audio format
|
* @param configuration containing the requested output audio format
|
||||||
* @return audio convert or null
|
* @return audio convert or null
|
||||||
*/
|
*/
|
||||||
public static IAudioConverter getAudioConverter(BroadcastConfiguration configuration, AudioSampleRate audioSampleRate,
|
public static IAudioConverter getAudioConverter(BroadcastConfiguration configuration, InputAudioFormat inputAudioFormat,
|
||||||
MP3Setting mp3Setting)
|
MP3Setting mp3Setting)
|
||||||
{
|
{
|
||||||
switch(configuration.getBroadcastFormat())
|
switch(configuration.getBroadcastFormat())
|
||||||
{
|
{
|
||||||
case MP3:
|
case MP3:
|
||||||
return new MP3AudioConverter(audioSampleRate, mp3Setting);
|
return new MP3AudioConverter(inputAudioFormat, mp3Setting);
|
||||||
default:
|
default:
|
||||||
mLog.info("Unrecognized broadcastAudio format: " + configuration.getBroadcastFormat().name());
|
mLog.info("Unrecognized broadcastAudio format: " + configuration.getBroadcastFormat().name());
|
||||||
}
|
}
|
||||||
@@ -140,12 +140,12 @@ public class BroadcastFactory
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ISilenceGenerator getSilenceGenerator(BroadcastFormat format, AudioSampleRate audioSampleRate, MP3Setting mp3Setting)
|
public static ISilenceGenerator getSilenceGenerator(BroadcastFormat format, InputAudioFormat inputAudioFormat, MP3Setting mp3Setting)
|
||||||
{
|
{
|
||||||
switch(format)
|
switch(format)
|
||||||
{
|
{
|
||||||
case MP3:
|
case MP3:
|
||||||
return new MP3SilenceGenerator(audioSampleRate, mp3Setting);
|
return new MP3SilenceGenerator(inputAudioFormat, mp3Setting);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unrecognized broadcast format [" + format +
|
throw new IllegalArgumentException("Unrecognized broadcast format [" + format +
|
||||||
"] can't create silence generator");
|
"] can't create silence generator");
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import io.github.dsheirer.audio.broadcast.AbstractAudioBroadcaster;
|
|||||||
import io.github.dsheirer.audio.broadcast.AudioRecording;
|
import io.github.dsheirer.audio.broadcast.AudioRecording;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastEvent;
|
import io.github.dsheirer.audio.broadcast.BroadcastEvent;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.gui.playlist.radioreference.RadioReferenceDecoder;
|
import io.github.dsheirer.gui.playlist.radioreference.RadioReferenceDecoder;
|
||||||
import io.github.dsheirer.identifier.Form;
|
import io.github.dsheirer.identifier.Form;
|
||||||
@@ -83,7 +83,7 @@ public class BroadcastifyCallBroadcaster extends AbstractAudioBroadcaster<Broadc
|
|||||||
* @param config to use
|
* @param config to use
|
||||||
* @param aliasModel for access to aliases
|
* @param aliasModel for access to aliases
|
||||||
*/
|
*/
|
||||||
public BroadcastifyCallBroadcaster(BroadcastifyCallConfiguration config, AudioSampleRate audioSampleRate,
|
public BroadcastifyCallBroadcaster(BroadcastifyCallConfiguration config, InputAudioFormat inputAudioFormat,
|
||||||
MP3Setting mp3Setting, AliasModel aliasModel)
|
MP3Setting mp3Setting, AliasModel aliasModel)
|
||||||
{
|
{
|
||||||
super(config);
|
super(config);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import io.github.dsheirer.alias.AliasModel;
|
|||||||
import io.github.dsheirer.audio.broadcast.AudioStreamingBroadcaster;
|
import io.github.dsheirer.audio.broadcast.AudioStreamingBroadcaster;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
import io.github.dsheirer.audio.broadcast.BroadcastConfiguration;
|
||||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
|
|
||||||
public abstract class IcecastAudioBroadcaster extends AudioStreamingBroadcaster
|
public abstract class IcecastAudioBroadcaster extends AudioStreamingBroadcaster
|
||||||
@@ -30,10 +30,10 @@ public abstract class IcecastAudioBroadcaster extends AudioStreamingBroadcaster
|
|||||||
private IBroadcastMetadataUpdater mMetadataUpdater;
|
private IBroadcastMetadataUpdater mMetadataUpdater;
|
||||||
private AliasModel mAliasModel;
|
private AliasModel mAliasModel;
|
||||||
|
|
||||||
public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration, AudioSampleRate audioSampleRate,
|
public IcecastAudioBroadcaster(BroadcastConfiguration broadcastConfiguration, InputAudioFormat inputAudioFormat,
|
||||||
MP3Setting mp3Setting, AliasModel aliasModel)
|
MP3Setting mp3Setting, AliasModel aliasModel)
|
||||||
{
|
{
|
||||||
super(broadcastConfiguration, audioSampleRate, mp3Setting);
|
super(broadcastConfiguration, inputAudioFormat, mp3Setting);
|
||||||
mAliasModel = aliasModel;
|
mAliasModel = aliasModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ package io.github.dsheirer.audio.broadcast.icecast;
|
|||||||
|
|
||||||
import io.github.dsheirer.alias.AliasModel;
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.properties.SystemProperties;
|
import io.github.dsheirer.properties.SystemProperties;
|
||||||
@@ -70,10 +70,10 @@ public class IcecastHTTPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
*
|
*
|
||||||
* @param configuration for the Icecast stream
|
* @param configuration for the Icecast stream
|
||||||
*/
|
*/
|
||||||
public IcecastHTTPAudioBroadcaster(IcecastHTTPConfiguration configuration, AudioSampleRate audioSampleRate,
|
public IcecastHTTPAudioBroadcaster(IcecastHTTPConfiguration configuration, InputAudioFormat inputAudioFormat,
|
||||||
MP3Setting mp3Setting, AliasModel aliasModel)
|
MP3Setting mp3Setting, AliasModel aliasModel)
|
||||||
{
|
{
|
||||||
super(configuration, audioSampleRate, mp3Setting, aliasModel);
|
super(configuration, inputAudioFormat, mp3Setting, aliasModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ package io.github.dsheirer.audio.broadcast.icecast;
|
|||||||
import io.github.dsheirer.alias.AliasModel;
|
import io.github.dsheirer.alias.AliasModel;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||||
import io.github.dsheirer.audio.broadcast.icecast.codec.IcecastCodecFactory;
|
import io.github.dsheirer.audio.broadcast.icecast.codec.IcecastCodecFactory;
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.properties.SystemProperties;
|
import io.github.dsheirer.properties.SystemProperties;
|
||||||
@@ -68,10 +68,10 @@ public class IcecastTCPAudioBroadcaster extends IcecastAudioBroadcaster
|
|||||||
*
|
*
|
||||||
* @param configuration for the Icecast stream
|
* @param configuration for the Icecast stream
|
||||||
*/
|
*/
|
||||||
public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration, AudioSampleRate audioSampleRate,
|
public IcecastTCPAudioBroadcaster(IcecastTCPConfiguration configuration, InputAudioFormat inputAudioFormat,
|
||||||
MP3Setting mp3Setting, AliasModel aliasModel)
|
MP3Setting mp3Setting, AliasModel aliasModel)
|
||||||
{
|
{
|
||||||
super(configuration, audioSampleRate, mp3Setting, aliasModel);
|
super(configuration, inputAudioFormat, mp3Setting, aliasModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import io.github.dsheirer.alias.AliasModel;
|
|||||||
import io.github.dsheirer.audio.broadcast.AudioStreamingBroadcaster;
|
import io.github.dsheirer.audio.broadcast.AudioStreamingBroadcaster;
|
||||||
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
import io.github.dsheirer.audio.broadcast.BroadcastState;
|
||||||
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
import io.github.dsheirer.audio.broadcast.IBroadcastMetadataUpdater;
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.util.ThreadPool;
|
import io.github.dsheirer.util.ThreadPool;
|
||||||
import org.apache.mina.core.RuntimeIoException;
|
import org.apache.mina.core.RuntimeIoException;
|
||||||
@@ -63,10 +63,10 @@ public class ShoutcastV1AudioBroadcaster extends AudioStreamingBroadcaster
|
|||||||
*
|
*
|
||||||
* @param configuration for the Shoutcast stream
|
* @param configuration for the Shoutcast stream
|
||||||
*/
|
*/
|
||||||
public ShoutcastV1AudioBroadcaster(ShoutcastV1Configuration configuration, AudioSampleRate audioSampleRate,
|
public ShoutcastV1AudioBroadcaster(ShoutcastV1Configuration configuration, InputAudioFormat inputAudioFormat,
|
||||||
MP3Setting mp3Setting, AliasModel aliasModel)
|
MP3Setting mp3Setting, AliasModel aliasModel)
|
||||||
{
|
{
|
||||||
super(configuration, audioSampleRate, mp3Setting);
|
super(configuration, inputAudioFormat, mp3Setting);
|
||||||
mAliasModel = aliasModel;
|
mAliasModel = aliasModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageF
|
|||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageType;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMessageType;
|
||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMetadata;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxMetadata;
|
||||||
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxProtocolFactory;
|
import io.github.dsheirer.audio.broadcast.shoutcast.v2.ultravox.UltravoxProtocolFactory;
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.identifier.Form;
|
import io.github.dsheirer.identifier.Form;
|
||||||
import io.github.dsheirer.identifier.Identifier;
|
import io.github.dsheirer.identifier.Identifier;
|
||||||
@@ -93,10 +93,10 @@ public class ShoutcastV2AudioStreamingBroadcaster extends AudioStreamingBroadcas
|
|||||||
*
|
*
|
||||||
* @param configuration for the Shoutcast V2 stream
|
* @param configuration for the Shoutcast V2 stream
|
||||||
*/
|
*/
|
||||||
public ShoutcastV2AudioStreamingBroadcaster(ShoutcastV2Configuration configuration, AudioSampleRate audioSampleRate,
|
public ShoutcastV2AudioStreamingBroadcaster(ShoutcastV2Configuration configuration, InputAudioFormat inputAudioFormat,
|
||||||
MP3Setting mp3Setting, AliasModel aliasModel)
|
MP3Setting mp3Setting, AliasModel aliasModel)
|
||||||
{
|
{
|
||||||
super(configuration, audioSampleRate, mp3Setting);
|
super(configuration, inputAudioFormat, mp3Setting);
|
||||||
mAliasModel = aliasModel;
|
mAliasModel = aliasModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,14 +24,19 @@ import io.github.dsheirer.audio.AudioFormats;
|
|||||||
import javax.sound.sampled.AudioFormat;
|
import javax.sound.sampled.AudioFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enumeration of (input) audio sample rates for mono audio.
|
* Enumeration of MP3 input audio formats for mono audio.
|
||||||
*/
|
*/
|
||||||
public enum AudioSampleRate
|
public enum InputAudioFormat
|
||||||
{
|
{
|
||||||
SR_8000(AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO, "8000 Hz (no resample / default)"),
|
SR_8000(AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO, "16-Bit 8000 Hz (no resample)"),
|
||||||
SR_16000(AudioFormats.PCM_SIGNED_16_KHZ_16BITS_MONO, "16000 Hz"),
|
SR_16000(AudioFormats.PCM_SIGNED_16000_HZ_16_BIT_MONO, "16-Bit 16000 Hz"),
|
||||||
SR_22050(AudioFormats.PCM_SIGNED_22050_HZ_16BITS_MONO, "22050 Hz"),
|
SR_22050(AudioFormats.PCM_SIGNED_22050_HZ_16_BIT_MONO, "16-Bit 22050 Hz (default)"),
|
||||||
SR_44100(AudioFormats.PCM_SIGNED_44100_HZ_16BITS_MONO, "44100 Hz");
|
SR_44100(AudioFormats.PCM_SIGNED_44100_HZ_16_BIT_MONO, "16-Bit 44100 Hz"),
|
||||||
|
|
||||||
|
SR_32_8000(AudioFormats.PCM_SIGNED_8000_HZ_32_BIT_MONO, "32-Bit 8000 Hz (no resample)"),
|
||||||
|
SR_32_16000(AudioFormats.PCM_SIGNED_16000_HZ_32_BIT_MONO, "32-Bit 16000 Hz"),
|
||||||
|
SR_32_22050(AudioFormats.PCM_SIGNED_22050_HZ_32_BIT_MONO, "32-Bit 22050 Hz"),
|
||||||
|
SR_32_44100(AudioFormats.PCM_SIGNED_44100_HZ_32_BIT_MONO, "32-Bit 44100 Hz");
|
||||||
|
|
||||||
private AudioFormat mAudioFormat;
|
private AudioFormat mAudioFormat;
|
||||||
private String mLabel;
|
private String mLabel;
|
||||||
@@ -40,7 +45,7 @@ public enum AudioSampleRate
|
|||||||
* Constructs an instance
|
* Constructs an instance
|
||||||
* @param audioFormat for the specified sample rate
|
* @param audioFormat for the specified sample rate
|
||||||
*/
|
*/
|
||||||
AudioSampleRate(AudioFormat audioFormat, String label)
|
InputAudioFormat(AudioFormat audioFormat, String label)
|
||||||
{
|
{
|
||||||
mAudioFormat = audioFormat;
|
mAudioFormat = audioFormat;
|
||||||
mLabel = label;
|
mLabel = label;
|
||||||
@@ -49,9 +54,9 @@ public enum AudioSampleRate
|
|||||||
/**
|
/**
|
||||||
* Default sample rate
|
* Default sample rate
|
||||||
*/
|
*/
|
||||||
public static AudioSampleRate getDefault()
|
public static InputAudioFormat getDefault()
|
||||||
{
|
{
|
||||||
return SR_8000;
|
return SR_22050;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +34,7 @@ public class LameFactory
|
|||||||
* @param setting to apply to the encoder
|
* @param setting to apply to the encoder
|
||||||
* @return lame encoder
|
* @return lame encoder
|
||||||
*/
|
*/
|
||||||
public static LameEncoder getLameEncoder(AudioSampleRate input, MP3Setting setting)
|
public static LameEncoder getLameEncoder(InputAudioFormat input, MP3Setting setting)
|
||||||
{
|
{
|
||||||
return switch(setting)
|
return switch(setting)
|
||||||
{
|
{
|
||||||
@@ -52,13 +52,13 @@ public class LameFactory
|
|||||||
* @param sampleRate to resample to
|
* @param sampleRate to resample to
|
||||||
* @return resampler.
|
* @return resampler.
|
||||||
*/
|
*/
|
||||||
public static RealResampler getResampler(AudioSampleRate sampleRate)
|
public static RealResampler getResampler(InputAudioFormat sampleRate)
|
||||||
{
|
{
|
||||||
return switch(sampleRate)
|
return switch(sampleRate)
|
||||||
{
|
{
|
||||||
case SR_16000 -> new RealResampler(8000, 16000, 4096, 512);
|
case SR_16000, SR_32_16000 -> new RealResampler(8000, 16000, 4096, 512);
|
||||||
case SR_22050 -> new RealResampler(8000, 22050, 4096, 512);
|
case SR_22050, SR_32_22050 -> new RealResampler(8000, 22050, 4096, 512);
|
||||||
case SR_44100 -> new RealResampler(8000, 44100, 4096, 512);
|
case SR_44100, SR_32_44100 -> new RealResampler(8000, 44100, 4096, 512);
|
||||||
default -> throw new IllegalArgumentException("Unrecognized sample rate for resampling: " + sampleRate);
|
default -> throw new IllegalArgumentException("Unrecognized sample rate for resampling: " + sampleRate);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts PCM audio packets to Mono, MP3 encoded audio
|
||||||
|
*/
|
||||||
public class MP3AudioConverter implements IAudioConverter
|
public class MP3AudioConverter implements IAudioConverter
|
||||||
{
|
{
|
||||||
private final static Logger mLog = LoggerFactory.getLogger( MP3AudioConverter.class );
|
private final static Logger mLog = LoggerFactory.getLogger( MP3AudioConverter.class );
|
||||||
@@ -40,25 +43,33 @@ public class MP3AudioConverter implements IAudioConverter
|
|||||||
private RealResampler mResampler;
|
private RealResampler mResampler;
|
||||||
private ByteArrayOutputStream mMP3EncodedFramesStream = new ByteArrayOutputStream();
|
private ByteArrayOutputStream mMP3EncodedFramesStream = new ByteArrayOutputStream();
|
||||||
private byte[] mOutputFramesBuffer;
|
private byte[] mOutputFramesBuffer;
|
||||||
|
private InputAudioFormat mInputAudioFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts PCM 16-bit Little Endian audio packets to Mono, MP3 compressed audio.
|
* Constructs an instance.
|
||||||
*
|
*
|
||||||
* @param audioSampleRate for the desired input sample rate (resampled from default 8 kHz as needed)
|
* @param inputAudioFormat for the desired input sample rate and bit size (resampled from default 8 kHz as needed)
|
||||||
* @param setting to configure the LAME encoder
|
* @param setting to configure the LAME encoder
|
||||||
*/
|
*/
|
||||||
public MP3AudioConverter(AudioSampleRate audioSampleRate, MP3Setting setting)
|
public MP3AudioConverter(InputAudioFormat inputAudioFormat, MP3Setting setting)
|
||||||
{
|
{
|
||||||
mEncoder = LameFactory.getLameEncoder(audioSampleRate, setting);
|
mInputAudioFormat = inputAudioFormat;
|
||||||
|
mEncoder = LameFactory.getLameEncoder(inputAudioFormat, setting);
|
||||||
|
|
||||||
if(audioSampleRate != AudioSampleRate.SR_8000)
|
//Resampling is only required if desired input sample rate is not system default of 8kHz
|
||||||
|
if(inputAudioFormat != InputAudioFormat.SR_8000 && inputAudioFormat != InputAudioFormat.SR_32_8000)
|
||||||
{
|
{
|
||||||
mResampler = LameFactory.getResampler(audioSampleRate);
|
mResampler = LameFactory.getResampler(inputAudioFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
mOutputFramesBuffer = new byte[mEncoder.getPCMBufferSize()];
|
mOutputFramesBuffer = new byte[mEncoder.getPCMBufferSize()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the list of PCM audio packets to MP3 encoded.
|
||||||
|
* @param audioPackets of PCM audio sampled at 8 kHz
|
||||||
|
* @return encoded MP3 audio
|
||||||
|
*/
|
||||||
public List<byte[]> convert(List<float[]> audioPackets)
|
public List<byte[]> convert(List<float[]> audioPackets)
|
||||||
{
|
{
|
||||||
List<byte[]> converted = new ArrayList<>();
|
List<byte[]> converted = new ArrayList<>();
|
||||||
@@ -70,7 +81,17 @@ public class MP3AudioConverter implements IAudioConverter
|
|||||||
|
|
||||||
for(int x = 0; x < audioPackets.size(); x++)
|
for(int x = 0; x < audioPackets.size(); x++)
|
||||||
{
|
{
|
||||||
byte[] bytesToEncode = ConversionUtils.convertToSigned16BitSamples(audioPackets.get(x)).array();
|
byte[] bytesToEncode = null;
|
||||||
|
|
||||||
|
if(mInputAudioFormat.getAudioFormat().getSampleSizeInBits() == 16)
|
||||||
|
{
|
||||||
|
bytesToEncode = ConversionUtils.convertToSigned16BitSamples(audioPackets.get(x)).array();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytesToEncode = ConversionUtils.convertToSigned32BitSamples(audioPackets.get(x)).array();
|
||||||
|
}
|
||||||
|
|
||||||
int bytesToEncodePointer = 0;
|
int bytesToEncodePointer = 0;
|
||||||
|
|
||||||
int inputChunkSize = FastMath.min(mOutputFramesBuffer.length, bytesToEncode.length);
|
int inputChunkSize = FastMath.min(mOutputFramesBuffer.length, bytesToEncode.length);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class MP3FrameInspector
|
|||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
mLog.info("Starting ...");
|
mLog.info("Starting ...");
|
||||||
MP3SilenceGenerator gen = new MP3SilenceGenerator(AudioSampleRate.SR_8000, MP3Setting.getDefault());
|
MP3SilenceGenerator gen = new MP3SilenceGenerator(InputAudioFormat.SR_8000, MP3Setting.getDefault());
|
||||||
|
|
||||||
List<byte[]> audio = gen.generate(173);
|
List<byte[]> audio = gen.generate(173);
|
||||||
|
|
||||||
|
|||||||
@@ -31,16 +31,16 @@ public class MP3SilenceGenerator implements ISilenceGenerator
|
|||||||
public static final boolean CONSTANT_BIT_RATE = false;
|
public static final boolean CONSTANT_BIT_RATE = false;
|
||||||
|
|
||||||
private MP3AudioConverter mMP3AudioConverter;
|
private MP3AudioConverter mMP3AudioConverter;
|
||||||
private AudioSampleRate mAudioSampleRate;
|
private InputAudioFormat mInputAudioFormat;
|
||||||
private byte[] mPreviousPartialFrameData;
|
private byte[] mPreviousPartialFrameData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates MP3 audio silence frames
|
* Generates MP3 audio silence frames
|
||||||
*/
|
*/
|
||||||
public MP3SilenceGenerator(AudioSampleRate audioSampleRate, MP3Setting setting)
|
public MP3SilenceGenerator(InputAudioFormat inputAudioFormat, MP3Setting setting)
|
||||||
{
|
{
|
||||||
mAudioSampleRate = audioSampleRate;
|
mInputAudioFormat = inputAudioFormat;
|
||||||
mMP3AudioConverter = new MP3AudioConverter(audioSampleRate, setting);
|
mMP3AudioConverter = new MP3AudioConverter(inputAudioFormat, setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,7 +53,7 @@ public class MP3SilenceGenerator implements ISilenceGenerator
|
|||||||
double duration_secs = (double)duration_ms / 1000.0;
|
double duration_secs = (double)duration_ms / 1000.0;
|
||||||
|
|
||||||
//We generate silence at 8000 kHz, because it gets resampled by the silence generator to the target rate
|
//We generate silence at 8000 kHz, because it gets resampled by the silence generator to the target rate
|
||||||
int length = (int)(duration_secs * AudioSampleRate.SR_8000.getSampleRate());
|
int length = (int)(duration_secs * InputAudioFormat.SR_8000.getSampleRate());
|
||||||
|
|
||||||
List<float[]> silenceBuffers = new ArrayList<>();
|
List<float[]> silenceBuffers = new ArrayList<>();
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ public class MP3SilenceGenerator implements ISilenceGenerator
|
|||||||
{
|
{
|
||||||
mLog.debug("Starting ...");
|
mLog.debug("Starting ...");
|
||||||
|
|
||||||
MP3SilenceGenerator generator = new MP3SilenceGenerator(AudioSampleRate.SR_44100, MP3Setting.VBR_7);
|
MP3SilenceGenerator generator = new MP3SilenceGenerator(InputAudioFormat.SR_44100, MP3Setting.VBR_7);
|
||||||
|
|
||||||
int x = 100;
|
int x = 100;
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class MonoAudioOutput extends AudioOutput
|
|||||||
|
|
||||||
public MonoAudioOutput(Mixer mixer, UserPreferences userPreferences)
|
public MonoAudioOutput(Mixer mixer, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(mixer, MixerChannel.MONO, AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO,
|
super(mixer, MixerChannel.MONO, AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO,
|
||||||
AudioFormats.MONO_SOURCE_DATALINE_INFO, BUFFER_SIZE, userPreferences);
|
AudioFormats.MONO_SOURCE_DATALINE_INFO, BUFFER_SIZE, userPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************
|
/*
|
||||||
* sdrtrunk
|
* *****************************************************************************
|
||||||
* Copyright (C) 2014-2017 Dennis Sheirer
|
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
* ****************************************************************************
|
||||||
******************************************************************************/
|
*/
|
||||||
package io.github.dsheirer.audio.playback;
|
package io.github.dsheirer.audio.playback;
|
||||||
|
|
||||||
import io.github.dsheirer.audio.AudioFormats;
|
import io.github.dsheirer.audio.AudioFormats;
|
||||||
@@ -36,7 +36,7 @@ public class StereoAudioOutput extends AudioOutput
|
|||||||
|
|
||||||
public StereoAudioOutput(Mixer mixer, MixerChannel channel, UserPreferences userPreferences)
|
public StereoAudioOutput(Mixer mixer, MixerChannel channel, UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
super(mixer, channel, AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO, AudioFormats.STEREO_SOURCE_DATALINE_INFO,
|
super(mixer, channel, AudioFormats.PCM_SIGNED_8000_HZ_16BITS_STEREO, AudioFormats.STEREO_SOURCE_DATALINE_INFO,
|
||||||
BUFFER_SIZE, userPreferences);
|
BUFFER_SIZE, userPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package io.github.dsheirer.gui.preference.mp3;
|
package io.github.dsheirer.gui.preference.mp3;
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
import io.github.dsheirer.preference.mp3.MP3Preference;
|
import io.github.dsheirer.preference.mp3.MP3Preference;
|
||||||
@@ -43,7 +43,7 @@ public class MP3PreferenceEditor extends HBox
|
|||||||
private MP3Preference mMP3Preference;
|
private MP3Preference mMP3Preference;
|
||||||
private GridPane mEditorPane;
|
private GridPane mEditorPane;
|
||||||
private ComboBox<MP3Setting> mMP3SettingComboBox;
|
private ComboBox<MP3Setting> mMP3SettingComboBox;
|
||||||
private ComboBox<AudioSampleRate> mAudioSampleRateComboBox;
|
private ComboBox<InputAudioFormat> mAudioSampleRateComboBox;
|
||||||
|
|
||||||
public MP3PreferenceEditor(UserPreferences userPreferences)
|
public MP3PreferenceEditor(UserPreferences userPreferences)
|
||||||
{
|
{
|
||||||
@@ -96,12 +96,12 @@ public class MP3PreferenceEditor extends HBox
|
|||||||
return mMP3SettingComboBox;
|
return mMP3SettingComboBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ComboBox<AudioSampleRate> getAudioSampleRateComboBox()
|
private ComboBox<InputAudioFormat> getAudioSampleRateComboBox()
|
||||||
{
|
{
|
||||||
if(mAudioSampleRateComboBox == null)
|
if(mAudioSampleRateComboBox == null)
|
||||||
{
|
{
|
||||||
mAudioSampleRateComboBox = new ComboBox<>();
|
mAudioSampleRateComboBox = new ComboBox<>();
|
||||||
mAudioSampleRateComboBox.getItems().addAll(AudioSampleRate.values());
|
mAudioSampleRateComboBox.getItems().addAll(InputAudioFormat.values());
|
||||||
mAudioSampleRateComboBox.getSelectionModel().select(mMP3Preference.getAudioSampleRate());
|
mAudioSampleRateComboBox.getSelectionModel().select(mMP3Preference.getAudioSampleRate());
|
||||||
mAudioSampleRateComboBox.getSelectionModel().selectedItemProperty()
|
mAudioSampleRateComboBox.getSelectionModel().selectedItemProperty()
|
||||||
.addListener((observable, oldValue, newValue) -> mMP3Preference.setAudioSampleRate(newValue));
|
.addListener((observable, oldValue, newValue) -> mMP3Preference.setAudioSampleRate(newValue));
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ public class PlaybackPreferenceEditor extends HBox
|
|||||||
|
|
||||||
byte[] bytes = buffer.array();
|
byte[] bytes = buffer.array();
|
||||||
|
|
||||||
DataLine.Info info = new DataLine.Info(Clip.class, AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO);
|
DataLine.Info info = new DataLine.Info(Clip.class, AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO);
|
||||||
|
|
||||||
if(!AudioSystem.isLineSupported(info))
|
if(!AudioSystem.isLineSupported(info))
|
||||||
{
|
{
|
||||||
@@ -418,7 +418,7 @@ public class PlaybackPreferenceEditor extends HBox
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Clip clip = (Clip)AudioSystem.getLine(info);
|
Clip clip = (Clip)AudioSystem.getLine(info);
|
||||||
clip.open(AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO, bytes, 0, bytes.length);
|
clip.open(AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO, bytes, 0, bytes.length);
|
||||||
clip.start();
|
clip.start();
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package io.github.dsheirer.preference.mp3;
|
package io.github.dsheirer.preference.mp3;
|
||||||
|
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.preference.Preference;
|
import io.github.dsheirer.preference.Preference;
|
||||||
import io.github.dsheirer.preference.PreferenceType;
|
import io.github.dsheirer.preference.PreferenceType;
|
||||||
@@ -38,7 +38,7 @@ public class MP3Preference extends Preference
|
|||||||
private static final String PREFERENCE_KEY_AUDIO_MP3_SAMPLE_RATE = "audio.mp3.sample.rate";
|
private static final String PREFERENCE_KEY_AUDIO_MP3_SAMPLE_RATE = "audio.mp3.sample.rate";
|
||||||
private final static Logger mLog = LoggerFactory.getLogger(MP3Preference.class);
|
private final static Logger mLog = LoggerFactory.getLogger(MP3Preference.class);
|
||||||
private Preferences mPreferences = Preferences.userNodeForPackage(MP3Preference.class);
|
private Preferences mPreferences = Preferences.userNodeForPackage(MP3Preference.class);
|
||||||
private AudioSampleRate mAudioSampleRate;
|
private InputAudioFormat mInputAudioFormat;
|
||||||
private MP3Setting mMP3Setting;
|
private MP3Setting mMP3Setting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,36 +96,36 @@ public class MP3Preference extends Preference
|
|||||||
/**
|
/**
|
||||||
* Preferred audio sample rate for input to the LAME MP3 encoder
|
* Preferred audio sample rate for input to the LAME MP3 encoder
|
||||||
*/
|
*/
|
||||||
public AudioSampleRate getAudioSampleRate()
|
public InputAudioFormat getAudioSampleRate()
|
||||||
{
|
{
|
||||||
if(mAudioSampleRate == null)
|
if(mInputAudioFormat == null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String rate = mPreferences.get(PREFERENCE_KEY_AUDIO_MP3_SAMPLE_RATE, AudioSampleRate.getDefault().name());
|
String rate = mPreferences.get(PREFERENCE_KEY_AUDIO_MP3_SAMPLE_RATE, InputAudioFormat.getDefault().name());
|
||||||
mAudioSampleRate = AudioSampleRate.valueOf(rate);
|
mInputAudioFormat = InputAudioFormat.valueOf(rate);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
mLog.error("Error parsing mp3 setting preference", e);
|
mLog.error("Error parsing mp3 setting preference", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mAudioSampleRate == null)
|
if(mInputAudioFormat == null)
|
||||||
{
|
{
|
||||||
mAudioSampleRate = AudioSampleRate.getDefault();
|
mInputAudioFormat = InputAudioFormat.getDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mAudioSampleRate;
|
return mInputAudioFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the input Audio Sample Rate preference
|
* Sets the input Audio Sample Rate preference
|
||||||
*/
|
*/
|
||||||
public void setAudioSampleRate(AudioSampleRate audioSampleRate)
|
public void setAudioSampleRate(InputAudioFormat inputAudioFormat)
|
||||||
{
|
{
|
||||||
mAudioSampleRate = audioSampleRate;
|
mInputAudioFormat = inputAudioFormat;
|
||||||
mPreferences.put(PREFERENCE_KEY_AUDIO_MP3_SAMPLE_RATE, mAudioSampleRate.name());
|
mPreferences.put(PREFERENCE_KEY_AUDIO_MP3_SAMPLE_RATE, mInputAudioFormat.name());
|
||||||
notifyPreferenceUpdated();
|
notifyPreferenceUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ package io.github.dsheirer.record;
|
|||||||
|
|
||||||
import io.github.dsheirer.audio.AudioFormats;
|
import io.github.dsheirer.audio.AudioFormats;
|
||||||
import io.github.dsheirer.audio.AudioSegment;
|
import io.github.dsheirer.audio.AudioSegment;
|
||||||
import io.github.dsheirer.audio.convert.AudioSampleRate;
|
import io.github.dsheirer.audio.convert.InputAudioFormat;
|
||||||
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
import io.github.dsheirer.audio.convert.MP3AudioConverter;
|
||||||
import io.github.dsheirer.audio.convert.MP3Setting;
|
import io.github.dsheirer.audio.convert.MP3Setting;
|
||||||
import io.github.dsheirer.preference.UserPreferences;
|
import io.github.dsheirer.preference.UserPreferences;
|
||||||
@@ -93,10 +93,10 @@ public class AudioSegmentRecorder
|
|||||||
outputStream.write(id3Bytes);
|
outputStream.write(id3Bytes);
|
||||||
|
|
||||||
//Convert audio to MP3 and write to file
|
//Convert audio to MP3 and write to file
|
||||||
AudioSampleRate audioSampleRate = userPreferences.getMP3Preference().getAudioSampleRate();
|
InputAudioFormat inputAudioFormat = userPreferences.getMP3Preference().getAudioSampleRate();
|
||||||
MP3Setting mp3Setting = userPreferences.getMP3Preference().getMP3Setting();
|
MP3Setting mp3Setting = userPreferences.getMP3Preference().getMP3Setting();
|
||||||
|
|
||||||
MP3AudioConverter converter = new MP3AudioConverter(audioSampleRate, mp3Setting);
|
MP3AudioConverter converter = new MP3AudioConverter(inputAudioFormat, mp3Setting);
|
||||||
List<byte[]> mp3Frames = converter.convert(audioSegment.getAudioBuffers());
|
List<byte[]> mp3Frames = converter.convert(audioSegment.getAudioBuffers());
|
||||||
for(byte[] mp3Frame: mp3Frames)
|
for(byte[] mp3Frame: mp3Frames)
|
||||||
{
|
{
|
||||||
@@ -128,7 +128,7 @@ public class AudioSegmentRecorder
|
|||||||
{
|
{
|
||||||
if(audioSegment.hasAudio())
|
if(audioSegment.hasAudio())
|
||||||
{
|
{
|
||||||
WaveWriter writer = new WaveWriter(AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO, path);
|
WaveWriter writer = new WaveWriter(AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO, path);
|
||||||
|
|
||||||
for(float[] audioBuffer: audioSegment.getAudioBuffers())
|
for(float[] audioBuffer: audioSegment.getAudioBuffers())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,7 +66,48 @@ public class ConversionUtils
|
|||||||
|
|
||||||
for(float sample : samples)
|
for(float sample : samples)
|
||||||
{
|
{
|
||||||
converted.putShort((short)(sample * Short.MAX_VALUE));
|
if(sample > 1.0f)
|
||||||
|
{
|
||||||
|
converted.putShort(Short.MAX_VALUE);
|
||||||
|
}
|
||||||
|
else if(sample < -1.0f)
|
||||||
|
{
|
||||||
|
converted.putShort((short)-Short.MAX_VALUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
converted.putShort((short)(sample * Short.MAX_VALUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the float samples into a little-endian 32-bit sample byte buffer.
|
||||||
|
*
|
||||||
|
* @param samples - float array of sample data
|
||||||
|
* @return - little-endian 32-bit sample byte buffer
|
||||||
|
*/
|
||||||
|
public static ByteBuffer convertToSigned32BitSamples(float[] samples)
|
||||||
|
{
|
||||||
|
ByteBuffer converted = ByteBuffer.allocate(samples.length * 4);
|
||||||
|
converted.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
|
for(float sample : samples)
|
||||||
|
{
|
||||||
|
if(sample > 1.0f)
|
||||||
|
{
|
||||||
|
converted.putInt(Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
else if(sample < -1.0f)
|
||||||
|
{
|
||||||
|
converted.putInt(-Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
converted.putInt((int)(sample * Integer.MAX_VALUE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return converted;
|
return converted;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class MixerManager
|
|||||||
if(channel == MixerChannel.MONO)
|
if(channel == MixerChannel.MONO)
|
||||||
{
|
{
|
||||||
DataLine.Info info = new DataLine.Info(TargetDataLine.class,
|
DataLine.Info info = new DataLine.Info(TargetDataLine.class,
|
||||||
AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO);
|
AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO);
|
||||||
|
|
||||||
TargetDataLine dataLine;
|
TargetDataLine dataLine;
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ public class MixerManager
|
|||||||
|
|
||||||
if(dataLine != null)
|
if(dataLine != null)
|
||||||
{
|
{
|
||||||
return new RealMixerSource(dataLine, AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO,
|
return new RealMixerSource(dataLine, AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO,
|
||||||
new RealShortAdapter());
|
new RealShortAdapter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ public class MixerManager
|
|||||||
else //STEREO
|
else //STEREO
|
||||||
{
|
{
|
||||||
DataLine.Info info = new DataLine.Info(TargetDataLine.class,
|
DataLine.Info info = new DataLine.Info(TargetDataLine.class,
|
||||||
AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO);
|
AudioFormats.PCM_SIGNED_8000_HZ_16BITS_STEREO);
|
||||||
|
|
||||||
TargetDataLine dataLine;
|
TargetDataLine dataLine;
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ public class MixerManager
|
|||||||
|
|
||||||
if(dataLine != null)
|
if(dataLine != null)
|
||||||
{
|
{
|
||||||
return new RealMixerSource(dataLine, AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO,
|
return new RealMixerSource(dataLine, AudioFormats.PCM_SIGNED_8000_HZ_16BITS_STEREO,
|
||||||
new RealChannelShortAdapter(mixerConfig.getChannel()));
|
new RealChannelShortAdapter(mixerConfig.getChannel()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,12 +302,12 @@ public class MixerManager
|
|||||||
private static EnumSet<MixerChannel> getSupportedTargetChannels(Mixer mixer)
|
private static EnumSet<MixerChannel> getSupportedTargetChannels(Mixer mixer)
|
||||||
{
|
{
|
||||||
DataLine.Info stereoInfo = new DataLine.Info(TargetDataLine.class,
|
DataLine.Info stereoInfo = new DataLine.Info(TargetDataLine.class,
|
||||||
AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO);
|
AudioFormats.PCM_SIGNED_8000_HZ_16BITS_STEREO);
|
||||||
|
|
||||||
boolean stereoSupported = mixer.isLineSupported(stereoInfo);
|
boolean stereoSupported = mixer.isLineSupported(stereoInfo);
|
||||||
|
|
||||||
DataLine.Info monoInfo = new DataLine.Info(TargetDataLine.class,
|
DataLine.Info monoInfo = new DataLine.Info(TargetDataLine.class,
|
||||||
AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO);
|
AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO);
|
||||||
|
|
||||||
boolean monoSupported = mixer.isLineSupported(monoInfo);
|
boolean monoSupported = mixer.isLineSupported(monoInfo);
|
||||||
|
|
||||||
@@ -337,11 +337,11 @@ public class MixerManager
|
|||||||
List<MixerChannel> channels = new ArrayList<>();
|
List<MixerChannel> channels = new ArrayList<>();
|
||||||
|
|
||||||
DataLine.Info stereoInfo = new DataLine.Info(SourceDataLine.class,
|
DataLine.Info stereoInfo = new DataLine.Info(SourceDataLine.class,
|
||||||
AudioFormats.PCM_SIGNED_8KHZ_16BITS_STEREO);
|
AudioFormats.PCM_SIGNED_8000_HZ_16BITS_STEREO);
|
||||||
|
|
||||||
boolean stereoSupported = mixer.isLineSupported(stereoInfo);
|
boolean stereoSupported = mixer.isLineSupported(stereoInfo);
|
||||||
|
|
||||||
DataLine.Info monoInfo = new DataLine.Info(SourceDataLine.class, AudioFormats.PCM_SIGNED_8_KHZ_16BITS_MONO);
|
DataLine.Info monoInfo = new DataLine.Info(SourceDataLine.class, AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO);
|
||||||
|
|
||||||
boolean monoSupported = mixer.isLineSupported(monoInfo);
|
boolean monoSupported = mixer.isLineSupported(monoInfo);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user