Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/212.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何将两个mp3音频文件混合/叠加到一个mp3文件中(不串联)_Android_Audio_Merge_Mp3 - Fatal编程技术网

Android 如何将两个mp3音频文件混合/叠加到一个mp3文件中(不串联)

Android 如何将两个mp3音频文件混合/叠加到一个mp3文件中(不串联),android,audio,merge,mp3,Android,Audio,Merge,Mp3,我想将两个mp3文件合并成一个mp3文件。例如,如果第一个文件是1分钟,第二个文件是30秒,那么输出应该是一分钟。在这一分钟内,它应该播放两个文件。我不确定你是否想在安卓手机上这样做(因为你的标签),但如果我是对的,也许可以尝试,这是一个移动DAW(我自己没有试过) 如果你只是在不调整输出音量的情况下“混合”两个文件,你的输出可能会被剪辑。但是我不确定是否有可能在不解码的情况下“混合”两个mp3文件 如果您可以在PC上合并它们,请尝试,这是一个免费的桌面DAW。首先,为了混合两个音频文件,您需要

我想将两个mp3文件合并成一个mp3文件。例如,如果第一个文件是1分钟,第二个文件是30秒,那么输出应该是一分钟。在这一分钟内,它应该播放两个文件。

我不确定你是否想在安卓手机上这样做(因为你的标签),但如果我是对的,也许可以尝试,这是一个移动DAW(我自己没有试过)

如果你只是在不调整输出音量的情况下“混合”两个文件,你的输出可能会被剪辑。但是我不确定是否有可能在不解码的情况下“混合”两个mp3文件


如果您可以在PC上合并它们,请尝试,这是一个免费的桌面DAW。

首先,为了混合两个音频文件,您需要操纵它们的原始表示法;由于MP3文件是压缩的,您无法直接访问信号的原始表示法。您需要解码压缩后的音频文件MP3流,以便“了解”您的音频信号的波形,然后您将能够混合它们

因此,为了将两个压缩音频文件混合成一个压缩音频文件,需要执行以下步骤:

  • 使用解码器解码压缩文件以获取原始数据(没有可用于此目的的公共系统API,您需要手动执行!
  • < > >强>混合<强>两个原始未压缩数据流(如果需要应用音频剪辑)。为此,您需要考虑使用解码器()获得的原始数据格式。
  • 将原始混合数据编码到压缩的MP3文件中(根据解码器,您需要使用编码器手动执行此操作)

  • 可以找到更多关于MP3解码器的信息。

    我没有找到任何好的解决方案。但是我们可以在这里做一些技巧:)
    您可以将这两个mp3文件分配给两个不同的MediaPlayer对象。然后使用按钮一次播放这两个文件。比较这两个mp3文件以查找最长的持续时间。然后使用AudioReorder录制到该持续时间。这会解决你的问题。我知道这不是一个正确的方法,但希望它能帮助你

    我没有用安卓系统做过,但我是用AdobeFlex做的。我想逻辑是一样的。我遵循以下步骤:

    • 我将这两个MP3提取到两个字节的数组中。(
      song1ByteArray
      song2ByteArray
    • 找出较大的字节数组。(假设
      song1ByteArray
      是较大的一个)
    • 创建一个返回混合字节数组的函数

      private ByteArray mix2Songs(ByteArray song1ByteArray, ByteArray song2ByteArray){
      int arrLength=song1ByteArray.length; 
      for(int i=0;i<arrLength;i+=8){ // here if you see we are incrementing the length by 8 because a sterio sound has both left and right channels 4 bytes for left +4 bytes for right.
          // read left and right channel values for the first song
          float source1_L=song1ByteArray.readFloat();// I'm not sure if readFloat() function exists in android but there will be an equivalant one.
          float source1_R=song1ByteArray.readFloat(); 
          float source2_L=0;
          float source2_R=0;
          if(song2ByteArray.bytesAvailable>0){
              source2_L=song1ByteArray.readFloat();//left channel of audio song2ByteArray
              source2_R=song1ByteArray.readFloat(); //right channel of audio song2ByteArray
          }
          returnResultArr.writeFloat((source_1_L+source_2_L)/2); // average value of the source 1 and 2 left channel
          returnResultArr.writeFloat((source_1_R+source_2_R)/2); // average value of the source 1 and 2 right channel
      }
      return returnResultArr;
      }
      
      private ByteArray mix2Songs(ByteArray song1字节数组、ByteArray song2字节数组){
      int arrLength=song1ByteArray.length;
      对于(int i=0;i1。
      2.
      3.您可以利用混合两个音频文件
      例如:

      
      // First convert audiofile to audioinputstream
      
      audioInputStream = AudioSystem.getAudioInputStream(soundFile);
      audioInputStream2 = AudioSystem.getAudioInputStream(soundFile2);
      
      // Create one collection list object using arraylist then add all AudioInputStreams
      
      Collection list=new ArrayList();
      list.add(audioInputStream2);
      list.add(audioInputStream);
      
      // Then pass the audioformat and collection list to MixingAudioInputStream constructor
      
      MixingAudioInputStream mixer=new MixingAudioInputStream(audioFormat, list); 
      
      // Finally read data from mixed AudionInputStream and give it to SourceDataLine
      
      nBytesRead =mixer.read(abData, 0,abData.length);
      
      int nBytesWritten = line.write(abData, 0, nBytesRead);
      
      4.尝试使用
      -m
      混合选项 5.您可以使用所解释的语法和方法在与您类似的项目中使用JLayer库。他还为您提供了如何将该库集成到android应用程序中并直接重新编译jar的指南

      解释他的代码很容易完成您的任务:

      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;
      }
      
      公共静态字节[]解码(字符串路径、int-startMs、int-maxMs)
      抛出IOException,com.mindtherobot.libs.mpg.DecoderException{
      ByteArrayOutputStream扩展流=新的ByteArrayOutputStream(1024);
      float totalMs=0;
      布尔搜索=真;
      文件=新文件(路径);
      InputStream InputStream=新的BufferedInputStream(新文件InputStream(文件),8*1024);
      试一试{
      Bitstream Bitstream=新比特流(inputStream);
      解码器=新解码器();
      布尔完成=假;
      而(!完成){
      Header-frameHeader=bitstream.readFrame();
      if(frameHeader==null){
      完成=正确;
      }否则{
      totalMs+=frameHeader.ms_/u frame();
      如果(totalMs>=startMs){
      寻找=错误;
      }
      如果(!正在查找){
      SampleBuffer输出=(SampleBuffer)解码器.decodeFrame(帧头,位流);
      if(output.getSampleFrequency()!=44100
      ||output.getChannelCount()!=2){
      抛出新的com.mindtherobot.libs.mpg.DecoderException(“不支持单声道或非44100 MP3”);
      }
      short[]pcm=output.getBuffer();
      用于(简称s:pcm){
      超流写入(s&0xff);
      超流写入((s>>8)和0xff);
      }
      }
      如果(总毫秒>=(起始毫秒+最大毫秒)){
      完成=正确;
      }
      }
      closeFrame();
      }
      返回outStream.toByteArray();
      }捕获(比特流异常e){
      抛出新IOException(“比特流错误:+e”);
      }捕获(解码){
      Log.w(标签“解码器错误”,e);
      抛出新的com.mindtherobot.libs.mpg.DecoderException(e);
      }最后{
      IOUtils.safeClose(输入流);
      }
      }
      公共静态字节[]混合(字符串路径1,字符串路径2){
      字节[]pcm1=解码(路径1,0,60000);
      字节[]pcm2=解码(路径2,0,60000);
      int len1=pcm1.length;
      int len2=pcm2.1长度;
      字节[]pcmL;
      字节[]pcmS;
      int lenL;//最长的长度
      int lenS;//最短的长度
      if(len2>len1){
      lenL=len1;
      pcmL=pcm1;
      透镜=透镜2;
      pcmS=pcm2;
      }否则{
      lenL=len2;
      pcmL=pcm2;
      透镜=透镜1;
      pcmS=pcm1;
      } 
      for(int-idx=0;idx=镜头){
      样本=pcmL[idx];
      }否则{
      样品=pcmL[idx]+pcmS[idx];
      }
      样本=(int)(样本*.71);
      如果(样本>127)样本=127;
      如果(sample要合并(重叠)两个声音文件,可以使用

      这是你的电话号码

      在他们的示例中,您可以只输入所需的命令。因此,让我们讨论一下我们需要的命令

      -i [FISRST_FILE_PATH] -i [SECOND_FILE_PATH] -filter_complex amerge -ac 2 -c:a libmp3lame -q:a 4 [OUTPUT_FILE_PATH]
      
      对于第一个和第二个文件路径,您将获得声音文件的绝对路径。 1-如果在sto上
      -i [FISRST_FILE_PATH] -i [SECOND_FILE_PATH] -filter_complex amerge -ac 2 -c:a libmp3lame -q:a 4 [OUTPUT_FILE_PATH]
      
      String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/File Name.mp3"