안녕하세요 일주일쯤 고민하다가 질문 올립니다.
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을 쓰는게 나은지요? 혹시 그게 더 낫다면 참고할만한 곳좀 알려주세요 ㅜㅜ
고수님들의 조언 부탁드립니다. ㅜ