Skip to content

Commit

Permalink
Reduce / adapt volume of break track (fixes #47).
Browse files Browse the repository at this point in the history
  • Loading branch information
nwaldispuehl committed Jul 19, 2018
1 parent 168a23b commit c703106
Show file tree
Hide file tree
Showing 18 changed files with 156 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ retorte laboratories (retorte.ch) IntervalMusicCompositor change log

2018-xx-xx 2.x.x (not yet released)
--------------------------------------------------------------------------------
ADD #47 Reduce / adapt volume of break track.
FIX #46 BPM dialog: Music should stop when dialog is closed.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ private byte[] getByteArrayFrom(PlaylistItemFragment playlistItemFragment) throw
return soundHelper.generateSilenceOfLength((playlistItemFragment.getExtractDurationInSeconds()));
}

AudioInputStream leveledStream = soundHelper.getLeveledStream(playlistItemFragment.getAudioFile().getAudioInputStream(), getVolumeRatioOf(playlistItemFragment));
AudioInputStream leveledStream = soundHelper.getLeveledStream(playlistItemFragment.getAudioFile().getAudioInputStream(), getVolumeRatioOf(playlistItemFragment), playlistItemFragment.getVolume());
return soundHelper.getStreamPart(leveledStream, playlistItemFragment.getExtractStartInMilliseconds(), playlistItemFragment.getExtractDurationInMilliseconds());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ private void collectBreakTracks() {

private void createPlaylist() {
playlist = new Playlist(compilationParameters, messageProducer);
playlist.generatePlaylist(musicPlaylistCandidates, compilationParameters.getMusicPattern(), breakPlaylistCandidates, compilationParameters.getBreakPattern(), compilationParameters.getIterations(), compilationParameters.getSoundEffectOccurrences());
playlist.generatePlaylist(musicPlaylistCandidates, compilationParameters.getMusicPattern(), breakPlaylistCandidates, compilationParameters.getBreakPattern(), compilationParameters.getBreakVolume(), compilationParameters.getIterations(), compilationParameters.getSoundEffectOccurrences());
}

private void createPlaylistReport() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void play(IAudioFile audioFile) {
AudioInputStream inputStream = null;
try {
inputStream = soundHelper.getLeveledStream(soundHelper.getStreamExtract(audioFile.getAudioInputStream(), extractStart, extractLength),
audioFile.getVolumeRatio());
audioFile.getVolumeRatio(), 1);
}
catch (IOException e) {
messageProducer.send(new ErrorMessage(e.getMessage()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public class BreakPlaylistItemFragment extends PlaylistItemFragment {

public BreakPlaylistItemFragment(PlaylistItemFragment playlistItemFragment) {
super(playlistItemFragment.getAudioFile(), playlistItemFragment.getExtractStartInMilliseconds(), playlistItemFragment.getExtractEndInMilliseconds());
super(playlistItemFragment.getAudioFile(), playlistItemFragment.getVolume(), playlistItemFragment.getExtractStartInMilliseconds(), playlistItemFragment.getExtractEndInMilliseconds());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,18 @@ public void generatePlaylist(List<IAudioFile> musicFiles,
List<Integer> musicPattern,
List<IAudioFile> breakFiles,
List<Integer> breakPattern,
double breakVolume,
Integer iterations,
List<SoundEffectOccurrence> soundEffectOccurrences) {
playlistItems = generatePlaylistFrom(musicFiles, musicPattern, breakFiles, breakPattern, iterations, soundEffectOccurrences);
playlistItems = generatePlaylistFrom(musicFiles, musicPattern, breakFiles, breakPattern, breakVolume, iterations, soundEffectOccurrences);
}

@VisibleForTesting
List<PlaylistItem> generatePlaylistFrom(List<IAudioFile> musicFiles,
List<Integer> musicPattern,
List<IAudioFile> breakFiles,
List<Integer> breakPattern,
double breakVolume,
Integer iterations,
List<SoundEffectOccurrence> soundEffectOccurrences) {

Expand All @@ -99,7 +101,7 @@ List<PlaylistItem> generatePlaylistFrom(List<IAudioFile> musicFiles,
}

List<PlaylistItemFragment> musicTracks = createMusicPlaylist(musicFiles, musicPattern, iterations);
List<PlaylistItemFragment> breakTracks = createBreakPlaylist(breakFiles, breakPattern, iterations, musicPattern.size());
List<PlaylistItemFragment> breakTracks = createBreakPlaylist(breakFiles, breakPattern, iterations, musicPattern.size(), breakVolume);

return createItemsWith(musicTracks, breakTracks, soundEffectOccurrences);
}
Expand Down Expand Up @@ -133,7 +135,7 @@ private List<PlaylistItemFragment> createMusicPlaylist(List<IAudioFile> musicFil
IAudioFile currentAudioFile = musicFiles.get((musicTrackCounter) % musicFiles.size());
int currentSoundPattern = musicPattern.get(musicPatternCounter % musicPattern.size());

PlaylistItemFragment newMusicTrack = createPlaylistItemFrom(currentAudioFile, currentSoundPattern * 1000);
PlaylistItemFragment newMusicTrack = createPlaylistItemFrom(currentAudioFile, 1, currentSoundPattern * 1000);
if (newMusicTrack != null) {
musicPlaylist.add(newMusicTrack);
musicPatternCounter++;
Expand Down Expand Up @@ -165,7 +167,7 @@ private void shuffle(List<IAudioFile> audioFiles) {
Collections.shuffle(audioFiles, random);
}

private List<PlaylistItemFragment> createBreakPlaylist(List<IAudioFile> breakFiles, List<Integer> breakPattern, Integer iterations, int musicPatternSize) {
private List<PlaylistItemFragment> createBreakPlaylist(List<IAudioFile> breakFiles, List<Integer> breakPattern, Integer iterations, int musicPatternSize, double volume) {
List<PlaylistItemFragment> breakPlaylist = Lists.newArrayList();

if (breakPattern.isEmpty() || hasSingleZero(breakPattern)) {
Expand All @@ -182,7 +184,7 @@ private List<PlaylistItemFragment> createBreakPlaylist(List<IAudioFile> breakFil
if (!breakFiles.isEmpty()) {
IAudioFile currentBreakFile = breakFiles.get((breakTrackCounter % musicPatternSize) % breakFiles.size());

PlaylistItemFragment newBreakTrack = createPlaylistItemFrom(currentBreakFile, currentBreakPatternMs);
PlaylistItemFragment newBreakTrack = createPlaylistItemFrom(currentBreakFile, volume, currentBreakPatternMs);
if (newBreakTrack != null) {
breakPlaylist.add(new BreakPlaylistItemFragment(newBreakTrack));
}
Expand All @@ -195,7 +197,7 @@ private List<PlaylistItemFragment> createBreakPlaylist(List<IAudioFile> breakFil
if (isCrossFadingMode()) {
currentBreakPatternMs += (long) (blendTime * 1000);
}
breakPlaylist.add(new BreakPlaylistItemFragment(createPlaylistItem(null, 0L, currentBreakPatternMs)));
breakPlaylist.add(new BreakPlaylistItemFragment(createPlaylistItem(null, volume, 0L, currentBreakPatternMs)));
}

breakTrackCounter++;
Expand All @@ -213,7 +215,7 @@ private boolean hasSingleZero(List<Integer> breakPattern) {
return breakPattern.size() == 1 && breakPattern.iterator().next() == 0;
}

private PlaylistItemFragment createPlaylistItemFrom(IAudioFile audioFile, long extractLengthInMilliseconds) {
private PlaylistItemFragment createPlaylistItemFrom(IAudioFile audioFile, double volume, long extractLengthInMilliseconds) {

long maximalRangeForDuration;
long trackStart = startCutOffInMilliseconds;
Expand Down Expand Up @@ -249,15 +251,15 @@ private PlaylistItemFragment createPlaylistItemFrom(IAudioFile audioFile, long e
currentProgress.put(audioFile, trackStart + extractLengthInMilliseconds);
}

return createPlaylistItem(audioFile, trackStart, trackStart + extractLengthInMilliseconds);
return createPlaylistItem(audioFile, volume, trackStart, trackStart + extractLengthInMilliseconds);
}

boolean hasSoundEffects() {
return playlistItems.stream().anyMatch(PlaylistItem::hasSoundEffects);
}

private PlaylistItemFragment createPlaylistItem(IAudioFile audioFile, Long startInMilliseconds, Long endInMilliseconds) {
return new PlaylistItemFragment(audioFile, startInMilliseconds, endInMilliseconds);
private PlaylistItemFragment createPlaylistItem(IAudioFile audioFile, double volume, Long startInMilliseconds, Long endInMilliseconds) {
return new PlaylistItemFragment(audioFile, volume, startInMilliseconds, endInMilliseconds);
}

long getTotalLength(Playlist playlist, List<PlaylistItem> playlistItems) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ public class PlaylistItemFragment {
//---- Fields

private final IAudioFile audioFile;
private final double volume;
private final long extractStartInMilliseconds;
private final long extractEndInMilliseconds;


//---- Constructor

PlaylistItemFragment(IAudioFile audioFile, long extractStartInMilliseconds, long extractEndInMilliseconds) {
PlaylistItemFragment(IAudioFile audioFile, double volume, long extractStartInMilliseconds, long extractEndInMilliseconds) {
this.audioFile = audioFile;
this.volume = volume;
this.extractStartInMilliseconds = extractStartInMilliseconds;
this.extractEndInMilliseconds = extractEndInMilliseconds;

Expand Down Expand Up @@ -50,6 +52,10 @@ public IAudioFile getAudioFile() {
return audioFile;
}

public double getVolume() {
return volume;
}

public long getExtractStartInMilliseconds() {
return extractStartInMilliseconds;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,17 @@ public int getAvgAmplitude(AudioInputStream inputBuffer, int sampleWindow) throw
return maxSample;
}

public AudioInputStream getLeveledStream(AudioInputStream audioInputStream, float desiredRelativeAmplitude) {
/**
* Adjusts the 'volume' (i.e. the amplitude) of the provided audio stream according to the measured volume ratio and an arbitrary volume factor.
*
* @param audioInputStream the stream holding the to be processed audio data.
* @param desiredRelativeAmplitude the relative amplitude to match.
* @param volume an arbitrary control factor, with e.g. 0.5 for half the volume.
* @return the amplified audio stream.
*/
public AudioInputStream getLeveledStream(AudioInputStream audioInputStream, float desiredRelativeAmplitude, double volume) {
AmplitudeAudioInputStream amplitudeAudioInputStream = new AmplitudeAudioInputStream(audioInputStream);
amplitudeAudioInputStream.setAmplitudeLinear(desiredRelativeAmplitude);
amplitudeAudioInputStream.setAmplitudeLinear((float) (desiredRelativeAmplitude * volume));
return amplitudeAudioInputStream;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ public class CompilationTest {
@Before
public void setup() throws IOException, UnsupportedAudioFileException {
musicFiles.add(audioFileFrom(TEST_SOUND));
breakFiles.add(audioFileFrom(TEST_SOUND));
}

@After
public void cleanup() throws IOException {
for (IAudioFile f : musicFiles) {
f.removeCache();
}
for (IAudioFile f : breakFiles) {
f.removeCache();
}
}

//---- Test methods
Expand Down Expand Up @@ -95,13 +99,49 @@ public void shouldGenerateLongerCompilation() throws IOException, UnsupportedAud
assertThat(compilation.length, is(44100 * 2 * 12));
}

@Test
public void shouldSetBreakVolume() throws IOException, UnsupportedAudioFileException {
// given
Playlist playList = playlistWith(1, l(1), l(1), 0.5);
ByteArrayOutputStream baos = new ByteArrayOutputStream();

// when
sut.generateCompilation(playList, baos);

// then
// Somehow check byte array...
byte[] compilation = baos.toByteArray();
assertThat(compilation.length, is(44100 * 2 * 2 * 2));

// Sound part
assertThat(compilation[0], is(b(0)));
assertThat(compilation[1], is(b(0)));
assertThat(compilation[88198], is(b(-20)));
assertThat(compilation[88199], is(b(-63)));
assertThat(compilation[176398], is(b(0)));
assertThat(compilation[176399], is(b(0)));

// Break part
assertThat(compilation[176400], is(b(0)));
assertThat(compilation[176401], is(b(0)));
assertThat(compilation[264598], is(b(-10)));
assertThat(compilation[264599], is(b(-32)));
assertThat(compilation[352798], is(b(0)));
assertThat(compilation[352798], is(b(0)));

}


//---- Helper methods

private Playlist playlistWith(int iterations, List<Integer> musicIntervals, List<Integer> breakIntervals) {
return playlistWith(iterations, musicIntervals, breakIntervals, 1);
}

private Playlist playlistWith(int iterations, List<Integer> musicIntervals, List<Integer> breakIntervals, double breakVolume) {
CompilationParameters parameters = new CompilationParameters();
Playlist playlist = new Playlist(parameters, m -> {});
playlist.generatePlaylist(musicFiles, musicIntervals, breakFiles, breakIntervals, iterations, newArrayList());
playlist.generatePlaylist(musicFiles, musicIntervals, breakFiles, breakIntervals, breakVolume, iterations, newArrayList());
return playlist;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class PlaylistItemFragmentTest {
@Test
public void shouldConsiderItselfSilentBreakIfAudioFileIsNull() {
// when
PlaylistItemFragment playlistItemFragment = new PlaylistItemFragment(null, 1, 2);
PlaylistItemFragment playlistItemFragment = new PlaylistItemFragment(null, 1, 1, 2);

// then
assertTrue(playlistItemFragment.isSilentBreak());
Expand All @@ -30,7 +30,7 @@ public void shouldReturnCorrectExtractDuration() {
// given
IAudioFile audioFile = mock(IAudioFile.class);
when(audioFile.getDuration()).thenReturn(10000L);
PlaylistItemFragment playlistItemFragment = new PlaylistItemFragment(audioFile, 500L, 1500L);
PlaylistItemFragment playlistItemFragment = new PlaylistItemFragment(audioFile, 1,500L, 1500L);

// when
long duration = playlistItemFragment.getExtractDurationInMilliseconds();
Expand Down
Loading

0 comments on commit c703106

Please sign in to comment.