Search code examples
javaaudiojava-audio

How do I take a WAV recording and change the amplitude of a part of it in Java?


Imagine having a recording of something saying "Hi there"

I'd like to chop/slice the WAV file between "Hi" and "there"

At this point, the "Hi" would be on one WAV file and the "there" on another wav file .e.g

hi.wav there.wav

From there, I'd like to change the volume/amplitude of the "there.wav" file.

Lastly, I'd like to merge the two wave files into:

hi_there.wav

Think of this as an audio editor, once finishing editing the audio, you would be able to save the edited audio as a brand new audio clip.


Solution

  • Cut the wave file:

    double [] music = read("music.wav");
    
    int start = 792478*2;
    int end = 1118153*2;
    
    double [] cutMusic = new double [end-start];
    
    for(int i = start; i < end; i++)
    {
        cutMusic [i-start] = music[i];
    }
    
    save("cutMusic.wav", cutMusic); //from StdAudio library
    

    Change the volume/amplitude:

    int multiplier = 0.5; //how much you want to change the volume by
    
    for(int i = 0; i < cutMusic.length;i++)
    {
        cutMusic[i] = multiplier * cutMusic[i];
    }
    

    Save the audio to a new wav file:

    save("cutmusic.wav"), cutMusic); //from the StdAudio library
    //converts the double array to a byte array
    

    Join the two files:

    ArrayList <File> joined = new ArrayList<>();
    
    joined.add(new File("music.wav"));
    joined.add(new File("cutMusic.wav"));
    
    AudioFormat format = new AudioFormat(
    
                    /*AudioFormat.Encoding*/AudioFormat.Encoding.PCM_SIGNED
                    /*float sampleRate*/, sampleRate
                    /*int sampleSizeInBits*/, 16
                    /*int channels*/, 2
                    /*int frameSize*/, 4
                    /*float frameRate*/, 44100,
                    /*boolean bigEndian*/false
    
    joinAudioFiles(format, joined, new File("joined.wav")); 
    //method needed is below
    
    public static void joinAudioFiles(AudioFormat audioFormat,
                                          java.util.List<File> audioFiles, File output) throws IOException,
                UnsupportedAudioFileException {
            output.getParentFile().mkdirs();
            output.delete();
            output.createNewFile();
    
            List<AudioInputStream> audioInputStreams = new ArrayList<AudioInputStream>();
            long totalFrameLength = 0;
            for (File audioFile : audioFiles) {
                AudioInputStream fileAudioInputStream = AudioSystem
                        .getAudioInputStream(audioFile);
                audioInputStreams.add(fileAudioInputStream);
                totalFrameLength += fileAudioInputStream.getFrameLength();
            }
    
            AudioInputStream sequenceInputStream = new AudioInputStream(
                    new SequenceInputStream(
                            Collections.enumeration(audioInputStreams)),
                    audioFormat, totalFrameLength);
            AudioSystem.write(sequenceInputStream, AudioFileFormat.Type.WAVE,
                    output);
        }