0

I've been learning Java to build what equates to an audio file merger/mixer.

The idea is to insert voice files into a 4 minute music bed.

I am able to create individual streams and output to different files, but I need to insert the data using an offset.

This is what I have so far. It throws an OutOfBounds Exception.

/**
     * @param files list of voice files and music file (at end of array)
     * @param outputName output file name
     * @throws IOException in case file IO messes up
     * @throws UnsupportedAudioFileException audio file errors
     */
    public void mix(ArrayList<String> files, String outputName) throws IOException, UnsupportedAudioFileException, LineUnavailableException {
        int offset = 2;
        int gap = 0;
        File outFile = new File(outputName);
        File music = new File(files.get(files.size()-1));
        AudioInputStream as = AudioSystem.getAudioInputStream(music);
        ByteArrayOutputStream b = new ByteArrayOutputStream(2 * (int) as.getFrameLength()+100);

        AudioSystem.write(as, AudioFileFormat.Type.WAVE ,b);
        
        for(String file : files) {
            if(!file.equals(files.get(files.size()-1))) {
                File f = new File(file);
                byte[] data = b.toByteArray();
                int out = AudioSystem.write(
                        AudioSystem.getAudioInputStream(f),
                        AudioFileFormat.Type.WAVE, b
                );
                b.write(data, 2, data.length);
                offset += getFile(file) + gap;
                
                AudioInputStream ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(data));
                AudioSystem.write(ais, AudioFileFormat.Type.WAVE, outFile);

                MixerLogging.writeToLogFile(String.format("Offset: %s %s\r\n", file, offset));
            }
        }

        MixerLogging.writeToLogFile(outFile.getName()+"\n");
    }

The getFile(file) method simply returns the file length in seconds.

Here is the error message:

Exception in thread "Timer-0" java.lang.IndexOutOfBoundsException: Range [2, 2 + 20512556) out of bounds for length 20512556
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromIndexSize(Preconditions.java:82)
    at java.base/jdk.internal.util.Preconditions.checkFromIndexSize(Preconditions.java:361)
    at java.base/java.util.Objects.checkFromIndexSize(Objects.java:411)
    at java.base/java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:129)
    at main.java.JMixer.mix(JMixer.java:68)
    at main.java.Database.getProds(Database.java:36)
    at main.java.Main$1.run(Main.java:17)
    at java.base/java.util.TimerThread.mainLoop(Timer.java:566)
    at java.base/java.util.TimerThread.run(Timer.java:516)

This is the line referred to in the error:

b.write(data, 2, data.length);

The end goal for this application is to mix the audio and output to a single file with a music bed and short voice tracks overlaid at a specific interval (say 10 seconds between voice files).

Any guidance would be greatly appreciated.

  • Please supply the exact error message. – Just another Java programmer Mar 28 '22 at 16:57
  • I just did thank you for reminding me – guitardave77 Mar 28 '22 at 17:03
  • This is basic programming and debugging you start from this line main.java.JMixer.mix(JMixer.java:68) and trace it -your logic seems cyclotic so for a beginner it seems to be wrong - if you cannot trace the error how are you coming up with such logic? – gpasch Mar 28 '22 at 21:11
  • I know exactly where the error is coming from. ```b.write(data, 2, data.length);``` – guitardave77 Mar 28 '22 at 22:00
  • 1
    I'm not clear what the goal is. When you say "insert into" do you mean that pieces of the audio files from various sources are to be concatenated? Or do you want to hear them playing concurrently (but with the voice files starting at designated positions)? Can you perhaps provide a simpler examplem or spell things out with a little more detail? FWIW, a lot of times when I see people (beginners with the javax.sound.sampled library) using ByteArray streams with audio, it's an attempt to do something that can be done more simply, but I can't tell if that's the case here. – Phil Freihofner Mar 29 '22 at 08:34
  • 1
    The title of this refers to making a single output file, but I see you calling a couple different AudioSystem.write() methods. If your intention is to blend sound sources together (like using an audio mixing unit) then the audio data from different sources will need to be converted to PCM data points and added together to produce a single stream. But I can't tell if that is what you want to do or not. – Phil Freihofner Mar 29 '22 at 08:43
  • Yessir that is exactly what I want to do. The end goal is to take a single music track and overlay shorter voice tracks at a specified interval- then output to a single, "mixed" file – guitardave77 Mar 29 '22 at 13:47
  • I was able to bypass the indexoutofbounds error by setting my offset to 0, but I'm still only getting the music data inserted into the output file and nothing else – guitardave77 Mar 29 '22 at 13:50

0 Answers0