/** * Creates a new default chain of audio processors, with the user-defined {@code * audioProcessors} applied before silence skipping and playback parameters. */ public DefaultAudioProcessorChain(AudioProcessor... audioProcessors) { this.audioProcessors = Arrays.copyOf(audioProcessors, audioProcessors.length + 2); silenceSkippingAudioProcessor = new SilenceSkippingAudioProcessor(); sonicAudioProcessor = new SonicAudioProcessor(); this.audioProcessors[audioProcessors.length] = silenceSkippingAudioProcessor; this.audioProcessors[audioProcessors.length + 1] = sonicAudioProcessor; }
/** * Sets the playback pitch. Calling this method will discard any data buffered within the * processor, and may update the value returned by {@link #isActive()}. * * @param pitch The requested new pitch. * @return The actual new pitch. */ public float setPitch(float pitch) { pitch = Util.constrainValue(pitch, MINIMUM_PITCH, MAXIMUM_PITCH); if (this.pitch != pitch) { this.pitch = pitch; sonic = null; } flush(); return pitch; }
@Override public PlaybackParameters applyPlaybackParameters(PlaybackParameters playbackParameters) { silenceSkippingAudioProcessor.setEnabled(playbackParameters.skipSilence); return new PlaybackParameters( sonicAudioProcessor.setSpeed(playbackParameters.speed), sonicAudioProcessor.setPitch(playbackParameters.pitch), playbackParameters.skipSilence); }
@Test public void testNoSampleRateChange() throws Exception { // Configure for resampling 44.1 kHz to 48 kHz. sonicAudioProcessor.setOutputSampleRateHz(48000); sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_16BIT); // Reconfigure to not modify the sample rate. sonicAudioProcessor.setOutputSampleRateHz(SonicAudioProcessor.SAMPLE_RATE_NO_CHANGE); sonicAudioProcessor.configure(22050, 2, C.ENCODING_PCM_16BIT); // The sample rate is unmodified, and the audio processor is not active. assertThat(sonicAudioProcessor.getOutputSampleRateHz()).isEqualTo(22050); assertThat(sonicAudioProcessor.isActive()).isFalse(); }
@Test public void testSampleRateChangeBecomesActiveAfterConfigure() throws Exception { // Configure for resampling 44.1 kHz to 48 kHz. sonicAudioProcessor.setOutputSampleRateHz(48000); sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_16BIT); // Set a new sample rate, which isn't active yet. sonicAudioProcessor.setOutputSampleRateHz(22050); assertThat(sonicAudioProcessor.getOutputSampleRateHz()).isEqualTo(48000); // The new sample rate takes effect on reconfiguration. sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_16BIT); assertThat(sonicAudioProcessor.getOutputSampleRateHz()).isEqualTo(22050); }
@Override public void flush() { if (isActive()) { if (sonic == null) { sonic = new Sonic(sampleRateHz, channelCount, speed, pitch, outputSampleRateHz); } else { sonic.flush(); } } outputBuffer = EMPTY_BUFFER; inputBytes = 0; outputBytes = 0; inputEnded = false; }
@Override public long getMediaDuration(long playoutDuration) { return sonicAudioProcessor.scaleDurationForSpeedup(playoutDuration); }
@Test public void testDoesNotSupportNon16BitInput() throws Exception { try { sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_8BIT); fail(); } catch (AudioProcessor.UnhandledFormatException e) { // Expected. } try { sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_24BIT); fail(); } catch (AudioProcessor.UnhandledFormatException e) { // Expected. } try { sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_32BIT); fail(); } catch (AudioProcessor.UnhandledFormatException e) { // Expected. } }
@Test public void testBecomesActiveAfterConfigure() throws Exception { sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_16BIT); // Set a new sample rate. sonicAudioProcessor.setOutputSampleRateHz(22050); // The new sample rate is not active yet. assertThat(sonicAudioProcessor.isActive()).isFalse(); assertThat(sonicAudioProcessor.getOutputSampleRateHz()).isEqualTo(44100); }
@Test public void testReconfigureWithSameSampleRate() throws Exception { // When configured for resampling from 44.1 kHz to 48 kHz, the output sample rate is correct. sonicAudioProcessor.setOutputSampleRateHz(48000); sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_16BIT); assertThat(sonicAudioProcessor.getOutputSampleRateHz()).isEqualTo(48000); assertThat(sonicAudioProcessor.isActive()).isTrue(); // When reconfigured with 48 kHz input, there is no resampling. sonicAudioProcessor.configure(48000, 2, C.ENCODING_PCM_16BIT); assertThat(sonicAudioProcessor.getOutputSampleRateHz()).isEqualTo(48000); assertThat(sonicAudioProcessor.isActive()).isFalse(); // When reconfigure with 44.1 kHz input, resampling is enabled again. sonicAudioProcessor.configure(44100, 2, C.ENCODING_PCM_16BIT); assertThat(sonicAudioProcessor.getOutputSampleRateHz()).isEqualTo(48000); assertThat(sonicAudioProcessor.isActive()).isTrue(); }
@Before public void setUp() { sonicAudioProcessor = new SonicAudioProcessor(); }
/** * Sets the playback speed. Calling this method will discard any data buffered within the * processor, and may update the value returned by {@link #isActive()}. * * @param speed The requested new playback speed. * @return The actual new playback speed. */ public float setSpeed(float speed) { speed = Util.constrainValue(speed, MINIMUM_SPEED, MAXIMUM_SPEED); if (this.speed != speed) { this.speed = speed; sonic = null; } flush(); return speed; }