diff --git a/src/main/java/io/github/dsheirer/audio/convert/InputAudioFormat.java b/src/main/java/io/github/dsheirer/audio/convert/InputAudioFormat.java index 8d3ad606..470b17da 100644 --- a/src/main/java/io/github/dsheirer/audio/convert/InputAudioFormat.java +++ b/src/main/java/io/github/dsheirer/audio/convert/InputAudioFormat.java @@ -20,6 +20,7 @@ package io.github.dsheirer.audio.convert; import io.github.dsheirer.audio.AudioFormats; +import java.util.EnumSet; import javax.sound.sampled.AudioFormat; @@ -29,8 +30,8 @@ import javax.sound.sampled.AudioFormat; public enum InputAudioFormat { SR_8000(AudioFormats.PCM_SIGNED_8000_HZ_16_BIT_MONO, "16-Bit 8000 Hz (no resample)"), - SR_16000(AudioFormats.PCM_SIGNED_16000_HZ_16_BIT_MONO, "16-Bit 16000 Hz"), - SR_22050(AudioFormats.PCM_SIGNED_22050_HZ_16_BIT_MONO, "16-Bit 22050 Hz (default)"), + SR_16000(AudioFormats.PCM_SIGNED_16000_HZ_16_BIT_MONO, "16-Bit 16000 Hz (default)"), + SR_22050(AudioFormats.PCM_SIGNED_22050_HZ_16_BIT_MONO, "16-Bit 22050 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)"), @@ -41,6 +42,17 @@ public enum InputAudioFormat private AudioFormat mAudioFormat; private String mLabel; + /** + * Set that includes sample rates of 8 or 16 kHz + */ + public static final EnumSet SAMPLE_RATES_8_16 = EnumSet.of(SR_8000, SR_32_8000, SR_16000, SR_32_16000); + + /** + * Set that includes sample rates of 8, 16, or 22 kHz + */ + public static final EnumSet SAMPLE_RATES_8_16_22 = EnumSet.of(SR_8000, SR_32_8000, SR_16000, + SR_32_16000, SR_22050, SR_32_22050); + /** * Constructs an instance * @param audioFormat for the specified sample rate @@ -56,7 +68,7 @@ public enum InputAudioFormat */ public static InputAudioFormat getDefault() { - return SR_22050; + return SR_16000; } /** diff --git a/src/main/java/io/github/dsheirer/audio/convert/MP3AudioConverter.java b/src/main/java/io/github/dsheirer/audio/convert/MP3AudioConverter.java index 9108e4c2..982021ee 100644 --- a/src/main/java/io/github/dsheirer/audio/convert/MP3AudioConverter.java +++ b/src/main/java/io/github/dsheirer/audio/convert/MP3AudioConverter.java @@ -60,8 +60,17 @@ public class MP3AudioConverter implements IAudioConverter mEncoder = LameFactory.getLameEncoder(inputAudioFormat, setting); mNormalizeAudio = normalizeAudio; + //Ensure input audio sample rate is supported for the MP3 setting and update as necessary - should never happen. + if((mInputAudioFormat.getSampleRate() - mEncoder.getEffectiveSampleRate()) > 1.0) + { + mInputAudioFormat = InputAudioFormat.getDefault(); + mLog.warn("MP3 setting [" + setting + "] does not support requested input audio sample rate [" + + inputAudioFormat + "] - using default sample rate [" + mInputAudioFormat + "]"); + mEncoder = LameFactory.getLameEncoder(inputAudioFormat, setting); + } + //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) + if(mInputAudioFormat != InputAudioFormat.SR_8000 && mInputAudioFormat != InputAudioFormat.SR_32_8000) { mResampler = LameFactory.getResampler(inputAudioFormat); } diff --git a/src/main/java/io/github/dsheirer/audio/convert/MP3Setting.java b/src/main/java/io/github/dsheirer/audio/convert/MP3Setting.java index 34a77a56..5cc0498e 100644 --- a/src/main/java/io/github/dsheirer/audio/convert/MP3Setting.java +++ b/src/main/java/io/github/dsheirer/audio/convert/MP3Setting.java @@ -19,6 +19,8 @@ package io.github.dsheirer.audio.convert; +import java.util.Arrays; +import java.util.List; import net.sourceforge.lame.mp3.Lame; /** @@ -79,6 +81,30 @@ public enum MP3Setting return mSetting; } + /** + * Input audio formats that are supported by the MP3Setting value. + * @return list of supported input audio sample rates. + */ + public List getSupportedSampleRates() + { + switch(this) + { + case CBR_16: + { + return InputAudioFormat.SAMPLE_RATES_8_16.stream().toList(); + } + case CBR_32: + case VBR_7: + { + return InputAudioFormat.SAMPLE_RATES_8_16_22.stream().toList(); + } + default: + { + return Arrays.stream(InputAudioFormat.values()).toList(); + } + } + } + @Override public String toString() { diff --git a/src/main/java/io/github/dsheirer/gui/preference/mp3/MP3PreferenceEditor.java b/src/main/java/io/github/dsheirer/gui/preference/mp3/MP3PreferenceEditor.java index f4995601..2f14772f 100644 --- a/src/main/java/io/github/dsheirer/gui/preference/mp3/MP3PreferenceEditor.java +++ b/src/main/java/io/github/dsheirer/gui/preference/mp3/MP3PreferenceEditor.java @@ -25,6 +25,7 @@ import io.github.dsheirer.preference.UserPreferences; import io.github.dsheirer.preference.mp3.MP3Preference; import javafx.geometry.HPos; import javafx.geometry.Insets; +import javafx.scene.control.Alert; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; @@ -99,12 +100,47 @@ public class MP3PreferenceEditor extends HBox mMP3SettingComboBox.getItems().addAll(MP3Setting.values()); mMP3SettingComboBox.getSelectionModel().select(mMP3Preference.getMP3Setting()); mMP3SettingComboBox.getSelectionModel().selectedItemProperty() - .addListener((observable, oldValue, newValue) -> mMP3Preference.setMP3Setting(newValue)); + .addListener((observable, oldValue, newValue) -> { + mMP3Preference.setMP3Setting(newValue); + updateAudioSampleRateComboBox(); + }); } return mMP3SettingComboBox; } + /** + * Updates the input sample rate combo box values and alerts the user whenever we auto-change an input sample rate + * due to a change in the MP3 setting value. + */ + private void updateAudioSampleRateComboBox() + { + InputAudioFormat currentSelection = getAudioSampleRateComboBox().getSelectionModel().getSelectedItem(); + MP3Setting setting = getMP3SettingComboBox().getSelectionModel().getSelectedItem(); + + getAudioSampleRateComboBox().getItems().clear(); + getAudioSampleRateComboBox().getItems().addAll(setting.getSupportedSampleRates()); + + if(currentSelection != null && getAudioSampleRateComboBox().getItems().contains(currentSelection)) + { + getAudioSampleRateComboBox().getSelectionModel().select(currentSelection); + } + else + { + getAudioSampleRateComboBox().getSelectionModel().select(InputAudioFormat.getDefault()); + + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Sample Rate Updated"); + alert.setHeaderText("Input Sample Rate Updated"); + + Label wrappingLabel = new Label("Previous input sample rate [" + currentSelection + + "] is not supported with encoder setting [" + setting + "]. Sample rate updated to default."); + wrappingLabel.setWrapText(true); + alert.getDialogPane().setContent(wrappingLabel); + alert.show(); + } + } + private ComboBox getAudioSampleRateComboBox() { if(mAudioSampleRateComboBox == null) @@ -113,7 +149,12 @@ public class MP3PreferenceEditor extends HBox mAudioSampleRateComboBox.getItems().addAll(InputAudioFormat.values()); mAudioSampleRateComboBox.getSelectionModel().select(mMP3Preference.getAudioSampleRate()); mAudioSampleRateComboBox.getSelectionModel().selectedItemProperty() - .addListener((observable, oldValue, newValue) -> mMP3Preference.setAudioSampleRate(newValue)); + .addListener((observable, oldValue, newValue) -> { + if(newValue != null) + { + mMP3Preference.setAudioSampleRate(newValue); + } + }); } return mAudioSampleRateComboBox; diff --git a/src/main/java/io/github/dsheirer/preference/mp3/MP3Preference.java b/src/main/java/io/github/dsheirer/preference/mp3/MP3Preference.java index 18ce7037..1090da26 100644 --- a/src/main/java/io/github/dsheirer/preference/mp3/MP3Preference.java +++ b/src/main/java/io/github/dsheirer/preference/mp3/MP3Preference.java @@ -116,6 +116,24 @@ public class MP3Preference extends Preference { mInputAudioFormat = InputAudioFormat.getDefault(); } + + //Ensure the input sample rate is supported by the MP3 setting, or change it to the first supported rate. + MP3Setting setting = getMP3Setting(); + + if(!setting.getSupportedSampleRates().contains(mInputAudioFormat)) + { + InputAudioFormat supportedAudioFormat = InputAudioFormat.getDefault(); + + //Default should always be supported by all mp3 settings, but fall-back to a supported rate if not. + if(!setting.getSupportedSampleRates().contains(supportedAudioFormat)) + { + supportedAudioFormat = setting.getSupportedSampleRates().get(0); + } + + mLog.warn("MP3 Setting [" + setting + "] does not support input sample rate [" + getAudioSampleRate().name() + + "] - updating to supported sample rate [" + supportedAudioFormat.name() + "]"); + setAudioSampleRate(supportedAudioFormat); + } } return mInputAudioFormat;