How to mix / overlay two mp3 audio file into one mp3 file (not concatenate)

前端 未结 7 1610
北荒
北荒 2020-12-14 09:23

I want to merge two mp3 files into one mp3 file.for example if 1st file is 1min and 2nd file is 30 sec then the output should be one min. In that one min it should play both

7条回答
  •  既然无缘
    2020-12-14 09:45

    This guy used the JLayer library in a project quite similar to yours. He also gives you a guide on how to integrate that library in your android application directly recompiling the jar.

    Paraphrasing his code it is very easy to accomplish your task:

    public static byte[] decode(String path, int startMs, int maxMs) 
      throws IOException, com.mindtherobot.libs.mpg.DecoderException {
      ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
    
      float totalMs = 0;
      boolean seeking = true;
    
      File file = new File(path);
      InputStream inputStream = new BufferedInputStream(new FileInputStream(file), 8 * 1024);
      try {
        Bitstream bitstream = new Bitstream(inputStream);
        Decoder decoder = new Decoder();
    
        boolean done = false;
        while (! done) {
          Header frameHeader = bitstream.readFrame();
          if (frameHeader == null) {
            done = true;
          } else {
            totalMs += frameHeader.ms_per_frame();
    
            if (totalMs >= startMs) {
              seeking = false;
            }
    
            if (! seeking) {
              SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
    
              if (output.getSampleFrequency() != 44100
                  || output.getChannelCount() != 2) {
                throw new com.mindtherobot.libs.mpg.DecoderException("mono or non-44100 MP3 not supported");
              }
    
              short[] pcm = output.getBuffer();
              for (short s : pcm) {
                outStream.write(s & 0xff);
                outStream.write((s >> 8 ) & 0xff);
              }
            }
    
            if (totalMs >= (startMs + maxMs)) {
              done = true;
            }
          }
          bitstream.closeFrame();
        }
    
        return outStream.toByteArray();
      } catch (BitstreamException e) {
        throw new IOException("Bitstream error: " + e);
      } catch (DecoderException e) {
        Log.w(TAG, "Decoder error", e);
        throw new com.mindtherobot.libs.mpg.DecoderException(e);
      } finally {
        IOUtils.safeClose(inputStream);     
      }
    }
    
    public static byte[] mix(String path1, String path2) {
        byte[] pcm1 = decode(path1, 0, 60000); 
        byte[] pcm2 = decode(path2, 0, 60000);
        int len1=pcm1.length; 
        int len2=pcm2.length;
        byte[] pcmL; 
        byte[] pcmS;
        int lenL; // length of the longest
        int lenS; // length of the shortest
        if (len2>len1) {
            lenL = len1;
            pcmL = pcm1;
            lenS = len2;                
            pcmS = pcm2;
        } else {
            lenL = len2;
            pcmL = pcm2;
            lenS = len1;                
            pcmS = pcm1;
        } 
        for (int idx = 0; idx < lenL; idx++) {
            int sample;
            if (idx >= lenS) {
                sample = pcmL[idx];
            } else {
                sample = pcmL[idx] + pcmS[idx];
            }
            sample=(int)(sample*.71);
            if (sample>127) sample=127;
            if (sample<-128) sample=-128;
            pcmL[idx] = (byte) sample;
        }
        return pcmL;
    }
    

    Note that I added attenuation and clipping in the last rows: you always have to do both when mixing two waveforms. If you don't have memory/time requirements you can make an int[] of the sum of the samples and evaluate what is the best attenuation to avoid clipping.

提交回复
热议问题