美文网首页
Android Media 05 --- 音频剪辑(MediaE

Android Media 05 --- 音频剪辑(MediaE

作者: 沪漂意哥哥 | 来源:发表于2022-04-23 00:00 被阅读0次

一. 描述

**将一段音频MP3文件,任意截取时间段(如10s-30s)区间,形成一个新的pcm文件(pcm加头部,可保存成wav文件)。

二. MusicProcess

public class MusicProcess {
   public void clip(String musicPath, String outPath, int startTime, int endTime) throws Exception {
       if (endTime < startTime) {
           return;
       }

       MediaExtractor mediaExtractor = new MediaExtractor();
       mediaExtractor.setDataSource(musicPath);
       int audioTrack = selectTrack(mediaExtractor );
       mediaExtractor.selectTrack(audioTrack);

       mediaExtractor.seekTo(startTime, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
       MediaFormat oriAudioFormat = mediaExtractor.getTrackFormat(audioTrack);
       int maxBufferSize = 100 * 1000;
       if (oriAudioFormat.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
           maxBufferSize = oriAudioFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
       } else {
           maxBufferSize = 100 * 1000;
       }
       ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize);
       MediaCodec mediaCodec = MediaCodec.createDecoderByType(oriAudioFormat.getString((MediaFormat.KEY_MIME)));
       mediaCodec.configure(oriAudioFormat, null, null, 0);
       File pcmFile = new File(Environment.getExternalStorageDirectory(), "out.pcm");
       FileChannel writeChannel = new FileOutputStream(pcmFile).getChannel();
       mediaCodec.start();
       MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
       int outputBufferIndex = -1;
       while (true) {
           int decodeInputIndex = mediaCodec.dequeueInputBuffer(100000);
           if (decodeInputIndex >= 0) {
               long sampleTimeUs = mediaExtractor.getSampleTime();
               if (sampleTimeUs == -1) {
                   break;
               } else if (sampleTimeUs < startTime) {
                   mediaExtractor.advance();
                   continue;
               } else if (sampleTimeUs > endTime) {
                   break;
               }
               info.size = mediaExtractor.readSampleData(buffer, 0);
               info.presentationTimeUs = sampleTimeUs;
               info.flags = mediaExtractor.getSampleFlags();

               byte[] content = new byte[buffer.remaining()];
               buffer.get(content);
               ByteBuffer inputBuffer = mediaCodec.getInputBuffer(decodeInputIndex);
               inputBuffer.put(content);
               mediaCodec.queueInputBuffer(decodeInputIndex, 0, info.size, info.presentationTimeUs, info.flags);
               mediaExtractor.advance();
           }

           outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 100_000);
           while (outputBufferIndex>=0) {
               ByteBuffer decodeOutputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
               writeChannel.write(decodeOutputBuffer);
               mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
               outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 100_000);
           }
       }

       writeChannel.close();
       mediaExtractor.release();
       mediaCodec.stop();
       mediaCodec.release();

       File wavFile = new File(Environment.getExternalStorageDirectory(),"output.wav" );
       new PcmToWavUtil(44100,  AudioFormat.CHANNEL_IN_STEREO,
               2, AudioFormat.ENCODING_PCM_16BIT).pcmToWav(pcmFile.getAbsolutePath()
               , wavFile.getAbsolutePath());
       Log.i("MusicProcess", "mixAudioTrack: 转换完毕");
   }

   private int selectTrack(MediaExtractor mediaExtractor) {
       int numTracks = mediaExtractor.getTrackCount();
       for (int i = 0; i < numTracks; i++) {
           MediaFormat format =mediaExtractor.getTrackFormat(i);
           String mime =   format.getString(MediaFormat.KEY_MIME);
           if (mime.startsWith("audio/")) {
               return i;
           }
       }
       return -1;
   }
}

三. PcmToWavUtil

public class PcmToWavUtil {
   private int mBufferSize;  //缓存的音频大小
   private int mSampleRate = 8000;// 8000|16000
   private int mChannelConfig = AudioFormat.CHANNEL_IN_STEREO;   //立体声
   private int mChannelCount = 2;
   private int mEncoding = AudioFormat.ENCODING_PCM_16BIT;

   public PcmToWavUtil() {
       this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannelConfig, mEncoding);
   }

   /**
    * @param sampleRate sample rate、采样率
    * @param channelConfig    channel、声道
    * @param encoding   Audio data format、音频格式
    */
   public PcmToWavUtil(int sampleRate, int channelConfig, int channelCount, int encoding) {
       this.mSampleRate = sampleRate;
       this.mChannelConfig = channelConfig;
       this.mChannelCount = channelCount;
       this.mEncoding = encoding;
       this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannelConfig, mEncoding);
   }

   /**
    * pcm文件转wav文件
    *
    * @param inFilename  源文件路径
    * @param outFilename 目标文件路径
    */
   public void pcmToWav(String inFilename, String outFilename) {
       FileInputStream in;
       FileOutputStream out;
       long totalAudioLen;
       long totalDataLen;
       long longSampleRate = mSampleRate;
       int channels = mChannelCount;
       long byteRate = 16 * mSampleRate * channels / 8;
       byte[] data = new byte[mBufferSize];
       try {
           in = new FileInputStream(inFilename);
           out = new FileOutputStream(outFilename);
           totalAudioLen = in.getChannel().size();
           totalDataLen = totalAudioLen + 36;

           writeWaveFileHeader(out, totalAudioLen, totalDataLen,
                   longSampleRate, channels, byteRate);
           while (in.read(data) != -1) {
               out.write(data);
           }
           in.close();
           out.close();
       }  catch (IOException e) {
           e.printStackTrace();
       }
   }

   /**
    * 加入wav文件头
    */
   private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                    long totalDataLen, long longSampleRate, int channels, long byteRate)
           throws IOException {
       byte[] header = new byte[44];
       header[0] = 'R'; // RIFF/WAVE header
       header[1] = 'I';
       header[2] = 'F';
       header[3] = 'F';
       header[4] = (byte) (totalDataLen & 0xff);
       header[5] = (byte) ((totalDataLen >> 8) & 0xff);
       header[6] = (byte) ((totalDataLen >> 16) & 0xff);
       header[7] = (byte) ((totalDataLen >> 24) & 0xff);
       header[8] = 'W';  //WAVE
       header[9] = 'A';
       header[10] = 'V';
       header[11] = 'E';
       header[12] = 'f'; // 'fmt ' chunk
       header[13] = 'm';
       header[14] = 't';
       header[15] = ' ';
       header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
       header[17] = 0;
       header[18] = 0;
       header[19] = 0;
       header[20] = 1;   // format = 1
       header[21] = 0;
       header[22] = (byte) channels;
       header[23] = 0;
       header[24] = (byte) (longSampleRate & 0xff);
       header[25] = (byte) ((longSampleRate >> 8) & 0xff);
       header[26] = (byte) ((longSampleRate >> 16) & 0xff);
       header[27] = (byte) ((longSampleRate >> 24) & 0xff);
       header[28] = (byte) (byteRate & 0xff);
       header[29] = (byte) ((byteRate >> 8) & 0xff);
       header[30] = (byte) ((byteRate >> 16) & 0xff);
       header[31] = (byte) ((byteRate >> 24) & 0xff);
       header[32] = (byte) (2 * 16 / 8); // block align
       header[33] = 0;
       header[34] = 16;  // bits per sample
       header[35] = 0;
       header[36] = 'd'; //data
       header[37] = 'a';
       header[38] = 't';
       header[39] = 'a';
       header[40] = (byte) (totalAudioLen & 0xff);
       header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
       header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
       header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
       out.write(header, 0, 44);
   }
}

相关文章

网友评论

      本文标题:Android Media 05 --- 音频剪辑(MediaE

      本文链接:https://www.haomeiwen.com/subject/rdwiertx.html