마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

MediaCodec을 이용하여 mp3를 pcm 파일로 변환하려고 합니다.

0 추천

안녕하세요 일주일쯤 고민하다가 질문 올립니다.

mp3에서 pcm 변환 방식은 mp3파일을 불러와서 미디어 코덱으로 디코딩을 하면서 나온 샘플데이터 값을 미리 만들어둔 pcm 파일에 계속 붙이는 방식입니다. 한번에 변환할수 있으면 좋겠는데 다른 방법은 잘 모르겠네요

코드는 다음과 같습니다.

 

ByteBuffer[] codecCvtInputBuffers;

ByteBuffer[] codecCvtOutputBuffers;

 

extractor = new MediaExtractor();

try {

extractor.setDataSource(test.mp3"); // 나중에 리스트에서 불러오도록 따로 처리예정

} catch (Exception e) {

Toast.makeText(this, “mp3 loading fail”, Toast.LENGTH_SHORT).show();

return;

}

 

MediaFormat format = extractor.getTrackFormat(0);

String mime = format.getString(MediaFormat.KEY_MIME);

 

 

codec = MediaCodec.createDecoderByType(mime);

codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);

codec.start();

codecCvtInputBuffers = codec.getInputBuffers();

codecCvtOutputBuffers = codec.getOutputBuffers();

 

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,

AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT), AudioTrack.MODE_STREAM);

 

audioTrack.play(); //플레이 하고 싶지 않은데 이걸 하지 않으면 정상적으로 저장이 되지 않음

extractor.selectTrack(0);

 

final long kTimeOutUs = 100000;

....

 

try {

String outputCvtFilePath = bgmFile.toString();

os = new FileOutputStream(outputCvtFilePath); // 메인에 선언되어 있음 (변환할 pcm 파일)

 

int r = 0;

while (!sawOutputEOS && noOutputCounter < noOutputCounterLimit && !doStop) {

noOutputCounter++;

if (!sawInputEOS) {

inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);

bufIndexCheck++;

if (inputBufIndex >= 0) {

ByteBuffer dstBuf = codecCvtInputBuffers[inputBufIndex];

int sampleSize = extractor.readSampleData(dstBuf, 0 /* offset */);

long presentationTimeUs = 0;

 

if (sampleSize < 0) {

sawInputEOS = true;

sampleSize = 0;

} else {

presentationTimeUs = extractor.getSampleTime();

}

 

codec.queueInputBuffer(inputBufIndex, 0 , sampleSize, presentationTimeUs,

sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);

 

if (!sawInputEOS) {

extractor.advance();

}

}

 

int res = codec.dequeueOutputBuffer(info, kTimeOutUs);

 

if (res >= 0) {

Log.d(LOG_TAG, "res : "+res);

Log.d(LOG_TAG, "got frame, size " + info.size + "/" +info.presentationTimeUs);

if (info.size > 0) {

noOutputCounter = 0;

}

 

int outputBufIndex = res;

ByteBuffer buf = codecCvtOutputBuffers[outputBufIndex];

 

byte[] chunk = new byte[info.size];

 

buf.get(chunk);

try {

os.write(chunk, 0, info.size);

} catch (IOException e) {

e.printStackTrace();

}

 

buf.clear();

if (chunk.length > 0) {

audioTrack.write(chunk, 0, chunk.length);

this.mState = State.Playing;

}

 

codec.releaseOutputBuffer(outputBufIndex, false /* render */);

if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {

sawOutputEOS = true;

} else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {

codecCvtOutputBuffers = codec.getOutputBuffers();

} else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {

MediaFormat oformat = codec.getOutputFormat();

}

r++;

 

} catch (FileNotFoundException e1) {

e1.printStackTrace();

}

 

Log.d(LOG_TAG, "stopping...");

 

Toast.makeText(this, "Converting End", Toast.LENGTH_SHORT).show();

 

this.mState = State.Stopped;

doStop = true;

 

플레이를 안시키고 한번에 mp3 파일을 pcm파일로 바꾸고 싶은데 어떻게 해야 할지 잘 모르겠네요

이런 경우에는 ffmpeg을 쓰는게 나은지요? 혹시 그게 더 낫다면 참고할만한 곳좀 알려주세요 ㅜㅜ

고수님들의 조언 부탁드립니다. ㅜ

밀랍인형 (130 포인트) 님이 2014년 9월 29일 질문

1개의 답변

+1 추천
끝나셨나요?? 저같은 경우방법이있는데 .
일탈99 (500 포인트) 님이 2014년 10월 16일 답변
어떤 방법인지 설명 좀 부탁드릴게요
...