2011-12-15 11 views
12

Puede usar MediaRecorder para grabar una secuencia directamente en AAC, pero no parece haber una forma de codificar un archivo PCM/WAV existente en AAC. La capacidad de codificar para AAC existe de forma nativa en Android y me gustaría usar eso. ¿No hay forma de hacerlo con un archivo de audio preexistente?Codificar wav a AAC en Android

Respuesta

1

puede ensuciarse las manos con el código nativo y utilizar la interfaz IOMX C++ para decodificadores en el marco. Pero esto es sensible a la construcción y no funcionará en otros teléfonos y sabores de Android.

Otra opción es portar un codificador aac de código abierto como ffmpeg y escribir una aplicación sobre él sobre jni. Al menos funcionará con teléfonos con la misma arquitectura (brazo-9, cortex a8 ...).

JB tiene un MediaCodec solo para satisfacer sus deseos. Pero el problema sería que la base de instalación de los dispositivos con JB se mantendrá durante algún tiempo más.

http://developer.android.com/about/versions/android-4.1.html#Multimedia

+0

¿Hay algún ejemplo de cómo utilizar MediaCodec? – Taras

3

mirada a esta hermosa (y perfecto estado de funcionamiento) ejemplo: Mp4ParserSample

mirada en la parte final de la clase (filas 335-442), el objeto convert Ejecutable ¡solo hace el trabajo! Debe configurar ese código según sus necesidades, ajustar las rutas de acceso de entrada y salida y los parámetros de conversión (tasa de muestreo, velocidad de bits, etc.).

public static final String AUDIO_RECORDING_FILE_NAME = "audio_Capturing-190814-034638.422.wav"; // Input PCM file 
public static final String COMPRESSED_AUDIO_FILE_NAME = "convertedmp4.m4a"; // Output MP4/M4A file 
public static final String COMPRESSED_AUDIO_FILE_MIME_TYPE = "audio/mp4a-latm"; 
public static final int COMPRESSED_AUDIO_FILE_BIT_RATE = 64000; // 64kbps 
public static final int SAMPLING_RATE = 48000; 
public static final int BUFFER_SIZE = 48000; 
public static final int CODEC_TIMEOUT_IN_MS = 5000; 
String LOGTAG = "CONVERT AUDIO"; 
Runnable convert = new Runnable() { 
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 
    @Override 
    public void run() { 
     android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); 
     try { 
      String filePath = Environment.getExternalStorageDirectory().getPath() + "/" + AUDIO_RECORDING_FILE_NAME; 
      File inputFile = new File(filePath); 
      FileInputStream fis = new FileInputStream(inputFile); 

      File outputFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + COMPRESSED_AUDIO_FILE_NAME); 
      if (outputFile.exists()) outputFile.delete(); 

      MediaMuxer mux = new MediaMuxer(outputFile.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); 

      MediaFormat outputFormat = MediaFormat.createAudioFormat(COMPRESSED_AUDIO_FILE_MIME_TYPE,SAMPLING_RATE, 1); 
      outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC); 
      outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, COMPRESSED_AUDIO_FILE_BIT_RATE); 
      outputFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 16384); 

      MediaCodec codec = MediaCodec.createEncoderByType(COMPRESSED_AUDIO_FILE_MIME_TYPE); 
      codec.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
      codec.start(); 

      ByteBuffer[] codecInputBuffers = codec.getInputBuffers(); // Note: Array of buffers 
      ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers(); 

      MediaCodec.BufferInfo outBuffInfo = new MediaCodec.BufferInfo(); 
      byte[] tempBuffer = new byte[BUFFER_SIZE]; 
      boolean hasMoreData = true; 
      double presentationTimeUs = 0; 
      int audioTrackIdx = 0; 
      int totalBytesRead = 0; 
      int percentComplete = 0; 
      do { 
       int inputBufIndex = 0; 
       while (inputBufIndex != -1 && hasMoreData) { 
        inputBufIndex = codec.dequeueInputBuffer(CODEC_TIMEOUT_IN_MS); 

        if (inputBufIndex >= 0) { 
         ByteBuffer dstBuf = codecInputBuffers[inputBufIndex]; 
         dstBuf.clear(); 

         int bytesRead = fis.read(tempBuffer, 0, dstBuf.limit()); 
         Log.e("bytesRead","Readed "+bytesRead); 
         if (bytesRead == -1) { // -1 implies EOS 
          hasMoreData = false; 
          codec.queueInputBuffer(inputBufIndex, 0, 0, (long) presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
         } else { 
          totalBytesRead += bytesRead; 
          dstBuf.put(tempBuffer, 0, bytesRead); 
          codec.queueInputBuffer(inputBufIndex, 0, bytesRead, (long) presentationTimeUs, 0); 
          presentationTimeUs = 1000000l * (totalBytesRead/2)/SAMPLING_RATE; 
         } 
        } 
       } 
       // Drain audio 
       int outputBufIndex = 0; 
       while (outputBufIndex != MediaCodec.INFO_TRY_AGAIN_LATER) { 
        outputBufIndex = codec.dequeueOutputBuffer(outBuffInfo, CODEC_TIMEOUT_IN_MS); 
        if (outputBufIndex >= 0) { 
         ByteBuffer encodedData = codecOutputBuffers[outputBufIndex]; 
         encodedData.position(outBuffInfo.offset); 
         encodedData.limit(outBuffInfo.offset + outBuffInfo.size); 
         if ((outBuffInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0 && outBuffInfo.size != 0) { 
          codec.releaseOutputBuffer(outputBufIndex, false); 
         }else{ 
          mux.writeSampleData(audioTrackIdx, codecOutputBuffers[outputBufIndex], outBuffInfo); 
          codec.releaseOutputBuffer(outputBufIndex, false); 
         } 
        } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 
         outputFormat = codec.getOutputFormat(); 
         Log.v(LOGTAG, "Output format changed - " + outputFormat); 
         audioTrackIdx = mux.addTrack(outputFormat); 
         mux.start(); 
        } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 
         Log.e(LOGTAG, "Output buffers changed during encode!"); 
        } else if (outputBufIndex == MediaCodec.INFO_TRY_AGAIN_LATER) { 
         // NO OP 
        } else { 
         Log.e(LOGTAG, "Unknown return code from dequeueOutputBuffer - " + outputBufIndex); 
        } 
       } 
       percentComplete = (int) Math.round(((float) totalBytesRead/(float) inputFile.length()) * 100.0); 
       Log.v(LOGTAG, "Conversion % - " + percentComplete); 
      } while (outBuffInfo.flags != MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
      fis.close(); 
      mux.stop(); 
      mux.release(); 
      Log.v(LOGTAG, "Compression done ..."); 
     } catch (FileNotFoundException e) { 
      Log.e(LOGTAG, "File not found!", e); 
     } catch (IOException e) { 
      Log.e(LOGTAG, "IO exception!", e); 
     } 

     //mStop = false; 
     // Notify UI thread... 
    } 
};