/** * Sets whether to skip silence in the input. Calling this method will discard any data buffered * within the processor, and may update the value returned by {@link #isActive()}. * * @param enabled Whether to skip silence in the input. */ public void setEnabled(boolean enabled) { this.enabled = enabled; flush(); }
@Override public void reset() { enabled = false; flush(); buffer = EMPTY_BUFFER; channelCount = Format.NO_VALUE; sampleRateHz = Format.NO_VALUE; paddingSize = 0; maybeSilenceBuffer = Util.EMPTY_BYTE_ARRAY; paddingBuffer = Util.EMPTY_BYTE_ARRAY; }
@Test public void testEnabledProcessor_isActive() throws Exception { // Given an enabled processor. silenceSkippingAudioProcessor.setEnabled(true); // When configuring it. boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); silenceSkippingAudioProcessor.flush(); // It's active. assertThat(reconfigured).isTrue(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); }
@Test public void testReconfiguringWithSameSampleRate_doesNotRequireReconfiguration() throws Exception { // Given an enabled processor and configured processor. silenceSkippingAudioProcessor.setEnabled(true); boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); assertThat(reconfigured).isTrue(); silenceSkippingAudioProcessor.flush(); // When reconfiguring it with the same sample rate. reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); // It's not reconfigured but it is active. assertThat(reconfigured).isFalse(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); }
@Test public void testChangingSampleRate_requiresReconfiguration() throws Exception { // Given an enabled processor and configured processor. silenceSkippingAudioProcessor.setEnabled(true); boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); if (reconfigured) { silenceSkippingAudioProcessor.flush(); } // When reconfiguring it with a different sample rate. reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ * 2, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); // It's reconfigured. assertThat(reconfigured).isTrue(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); }
/** * Processes the entire stream provided by {@code inputBufferProvider} in chunks of {@code * inputBufferSize} and returns the total number of output frames. */ private static long process( SilenceSkippingAudioProcessor processor, InputBufferProvider inputBufferProvider, int inputBufferSize) throws UnhandledFormatException { processor.flush(); long totalOutputFrames = 0; while (inputBufferProvider.hasRemaining()) { ByteBuffer inputBuffer = inputBufferProvider.getNextInputBuffer(inputBufferSize); while (inputBuffer.hasRemaining()) { processor.queueInput(inputBuffer); ByteBuffer outputBuffer = processor.getOutput(); totalOutputFrames += outputBuffer.remaining() / (2 * processor.getOutputChannelCount()); outputBuffer.clear(); } } processor.queueEndOfStream(); while (!processor.isEnded()) { ByteBuffer outputBuffer = processor.getOutput(); totalOutputFrames += outputBuffer.remaining() / (2 * processor.getOutputChannelCount()); outputBuffer.clear(); } return totalOutputFrames; }
@Test public void testSkipThenFlush_resetsSkippedFrameCount() throws Exception { // Given a signal that alternates between silence and noise. InputBufferProvider inputBufferProvider = getInputBufferProviderForAlternatingSilenceAndNoise( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, TEST_SIGNAL_SILENCE_DURATION_MS, TEST_SIGNAL_NOISE_DURATION_MS, TEST_SIGNAL_FRAME_COUNT); // When processing the entire signal then flushing. SilenceSkippingAudioProcessor silenceSkippingAudioProcessor = new SilenceSkippingAudioProcessor(); silenceSkippingAudioProcessor.setEnabled(true); boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); silenceSkippingAudioProcessor.flush(); assertThat(reconfigured).isTrue(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); process(silenceSkippingAudioProcessor, inputBufferProvider, INPUT_BUFFER_SIZE); silenceSkippingAudioProcessor.flush(); // The skipped frame count is zero. assertThat(silenceSkippingAudioProcessor.getSkippedFrames()).isEqualTo(0); }
@Test public void testSkipInSilentSignal_skipsEverything() throws Exception { // Given a signal with only noise. InputBufferProvider inputBufferProvider = getInputBufferProviderForAlternatingSilenceAndNoise( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, TEST_SIGNAL_SILENCE_DURATION_MS, /* noiseDurationMs= */ 0, TEST_SIGNAL_FRAME_COUNT); // When processing the entire signal. silenceSkippingAudioProcessor.setEnabled(true); boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); silenceSkippingAudioProcessor.flush(); assertThat(reconfigured).isTrue(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); long totalOutputFrames = process(silenceSkippingAudioProcessor, inputBufferProvider, INPUT_BUFFER_SIZE); // The entire signal is skipped. assertThat(totalOutputFrames).isEqualTo(0); assertThat(silenceSkippingAudioProcessor.getSkippedFrames()).isEqualTo(TEST_SIGNAL_FRAME_COUNT); }
@Test public void testSkipWithSmallerInputBufferSize_hasCorrectOutputAndSkippedFrameCounts() throws Exception { // Given a signal that alternates between silence and noise. InputBufferProvider inputBufferProvider = getInputBufferProviderForAlternatingSilenceAndNoise( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, TEST_SIGNAL_SILENCE_DURATION_MS, TEST_SIGNAL_NOISE_DURATION_MS, TEST_SIGNAL_FRAME_COUNT); // When processing the entire signal with a smaller input buffer size. SilenceSkippingAudioProcessor silenceSkippingAudioProcessor = new SilenceSkippingAudioProcessor(); silenceSkippingAudioProcessor.setEnabled(true); boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); silenceSkippingAudioProcessor.flush(); assertThat(reconfigured).isTrue(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); long totalOutputFrames = process(silenceSkippingAudioProcessor, inputBufferProvider, /* inputBufferSize= */ 80); // The right number of frames are skipped/output. assertThat(totalOutputFrames).isEqualTo(57980); assertThat(silenceSkippingAudioProcessor.getSkippedFrames()).isEqualTo(42020); }
@Test public void testSkipInNoisySignal_skipsNothing() throws Exception { // Given a signal with only silence. InputBufferProvider inputBufferProvider = getInputBufferProviderForAlternatingSilenceAndNoise( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, /* silenceDurationMs= */ 0, TEST_SIGNAL_NOISE_DURATION_MS, TEST_SIGNAL_FRAME_COUNT); // When processing the entire signal. SilenceSkippingAudioProcessor silenceSkippingAudioProcessor = new SilenceSkippingAudioProcessor(); silenceSkippingAudioProcessor.setEnabled(true); boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); silenceSkippingAudioProcessor.flush(); assertThat(reconfigured).isTrue(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); long totalOutputFrames = process(silenceSkippingAudioProcessor, inputBufferProvider, INPUT_BUFFER_SIZE); // None of the signal is skipped. assertThat(totalOutputFrames).isEqualTo(TEST_SIGNAL_FRAME_COUNT); assertThat(silenceSkippingAudioProcessor.getSkippedFrames()).isEqualTo(0); }
@Test public void testSkipWithLargerInputBufferSize_hasCorrectOutputAndSkippedFrameCounts() throws Exception { // Given a signal that alternates between silence and noise. InputBufferProvider inputBufferProvider = getInputBufferProviderForAlternatingSilenceAndNoise( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, TEST_SIGNAL_SILENCE_DURATION_MS, TEST_SIGNAL_NOISE_DURATION_MS, TEST_SIGNAL_FRAME_COUNT); // When processing the entire signal with a larger input buffer size. SilenceSkippingAudioProcessor silenceSkippingAudioProcessor = new SilenceSkippingAudioProcessor(); silenceSkippingAudioProcessor.setEnabled(true); boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); silenceSkippingAudioProcessor.flush(); assertThat(reconfigured).isTrue(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); long totalOutputFrames = process(silenceSkippingAudioProcessor, inputBufferProvider, /* inputBufferSize= */ 120); // The right number of frames are skipped/output. assertThat(totalOutputFrames).isEqualTo(57980); assertThat(silenceSkippingAudioProcessor.getSkippedFrames()).isEqualTo(42020); }
@Test public void testSkipInAlternatingTestSignal_hasCorrectOutputAndSkippedFrameCounts() throws Exception { // Given a signal that alternates between silence and noise. InputBufferProvider inputBufferProvider = getInputBufferProviderForAlternatingSilenceAndNoise( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, TEST_SIGNAL_SILENCE_DURATION_MS, TEST_SIGNAL_NOISE_DURATION_MS, TEST_SIGNAL_FRAME_COUNT); // When processing the entire signal. SilenceSkippingAudioProcessor silenceSkippingAudioProcessor = new SilenceSkippingAudioProcessor(); silenceSkippingAudioProcessor.setEnabled(true); boolean reconfigured = silenceSkippingAudioProcessor.configure( TEST_SIGNAL_SAMPLE_RATE_HZ, TEST_SIGNAL_CHANNEL_COUNT, C.ENCODING_PCM_16BIT); silenceSkippingAudioProcessor.flush(); assertThat(reconfigured).isTrue(); assertThat(silenceSkippingAudioProcessor.isActive()).isTrue(); long totalOutputFrames = process(silenceSkippingAudioProcessor, inputBufferProvider, INPUT_BUFFER_SIZE); // The right number of frames are skipped/output. assertThat(totalOutputFrames).isEqualTo(57980); assertThat(silenceSkippingAudioProcessor.getSkippedFrames()).isEqualTo(42020); }