0

AudioTrack で使用するオーディオ ファイルを PCM にデコードしようとしています。オーディオはきしみ、ぎこちなく、ただのぎくしゃくしていて、ランダムな秒の間、本来あるべきように聞こえますが、主に完全に混乱しています. どこに間違いがあるのか​​ わかりません.配列がplaySoundに返される方法にありますか?

事前に感謝します。しばらくの間、この問題について助けていただければ幸いです。

これは私のJavaコードです:

public void init() {
int bufSize = AudioTrack.getMinBufferSize(44100, 
                AudioFormat.CHANNEL_OUT_STEREO,  
                AudioFormat.ENCODING_PCM_16BIT); 


        track = new AudioTrack(AudioManager.STREAM_MUSIC,  
        44100,  
        AudioFormat.CHANNEL_OUT_STEREO,  
        AudioFormat.ENCODING_PCM_16BIT,  
        bufSize, 
        AudioTrack.MODE_STREAM); 
        log("STARTING!!! _________________________ <--");

        byte[] array = new byte[bufSize];

        try {

            fos  = new FileOutputStream("/sdcard/acdc.bin");

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        decoder("/sdcard/acdc.ogg", array); 
}

void playSound(byte[] buf, int size) {   

    try {
        fos.write(buf, 0, size);
    } catch (IOException e) {
        e.printStackTrace();
    }
    if(track.getPlayState()!=AudioTrack.PLAYSTATE_PLAYING) {   
        track.play();                       
    }
    int wrote =  track.write(buf, 0, size);
    if (wrote != size)
        log("WRITING: " + wrote  + " but size was: " + size); 
}

これは私のc関数です:

void Java_com_example_ffmpegsample_MainActivity_decoder(JNIEnv* env, jobject obj,jstring file,jbyteArray array)
    {
        jboolean            isfilenameCopy;
        const char *        filename = (*env)->GetStringUTFChars(env, file, &isfilenameCopy);
        AVCodec *codec;
        AVCodecContext *c= NULL;
        AVFormatContext *pFormatCtx;
        AVCodecContext *pCodecCtx;

        int out_size, len;
        FILE *f, *outfile;
        uint8_t *outbuf;
        uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
        AVPacket avpkt;
        LOGI("HERE");
        jclass              cls = (*env)->GetObjectClass(env, obj);
        LOGI(cls);
        jmethodID           play = (*env)->GetMethodID(env, cls, "playSound", "([BI)V");//At the begining of your main function

        av_init_packet(&avpkt);



        av_register_all();
        LOGI("AUDIO DECODER");
        printf("Audio decoding\n");
        int err;
        err = av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL);
        if (err!=0) {
            LOGI("COULD NOT AV_OPEN file");
            return;
        }
        if(av_find_stream_info(pFormatCtx)<0) {
                LOGE("Unable to get stream info");
                return;
        }
        int audioStream = -1;
        int i;

        for (i=0; i<pFormatCtx->nb_streams; i++) {
                if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) {
                    audioStream = i;
                    break;
                }
            }
            if(audioStream==-1) {
                LOGE("Unable to find audio stream");
                return;
            }
        LOGI("Audio stream is [%d]", audioStream);

        pCodecCtx=pFormatCtx->streams[audioStream]->codec;
        codec = avcodec_find_decoder(pCodecCtx->codec_id);
        /* find the mpeg audio decoder */
       // codec = avcodec_find_decoder(CODEC_ID_AAC);
        if (!codec) {
            LOGI("NO CODEC");
            fprintf(stderr, "codec not found\n");
            return;
        }

        //c= avcodec_alloc_context();
        c = pCodecCtx;

        /* open it */
        if (avcodec_open(c, codec) < 0) {
            fprintf(stderr, "could not open codec\n");
            LOGI("NOT LOADING CODEC");
            return;
        }

        outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);

        f = fopen(filename, "rb");
        if (!f) {
            fprintf(stderr, "could not open %s\n", filename);
            LOGI("COULD NOT OPEN FILE");
            return;
        }

        /* decode until eof */
        avpkt.data = inbuf;
        avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);

        while (avpkt.size > 0) {
            LOGI("............................." + avpkt.size);
            out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
            len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);
            if (len < 0) {
                fprintf(stderr, "Error while decoding\n");
                LOGI("ERROR DECODING, error: %d", len);
                return;
            }
            if (out_size > 0) {
                /* if a frame has been decoded, output it */
                jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL);
                memcpy(bytes, outbuf, out_size); //
                (*env)->ReleaseByteArrayElements(env, array, bytes, 0);
                (*env)->CallVoidMethod(env, obj, play, array, out_size);

            }
            avpkt.size -= len;
            avpkt.data += len;
            if (avpkt.size < AUDIO_REFILL_THRESH) {
                /* Refill the input buffer, to avoid trying to decode
                 * incomplete frames. Instead of this, one could also use
                 * a parser, or use a proper container format through
                 * libavformat. */
                memmove(inbuf, avpkt.data, avpkt.size);
                avpkt.data = inbuf;
                len = fread(avpkt.data + avpkt.size, 1,
                            AUDIO_INBUF_SIZE - avpkt.size, f);
                if (len > 0)
                    avpkt.size += len;
            }
        }

        fclose(f);
        free(outbuf);

        avcodec_close(c);
        av_free(c);
    }
4

2 に答える 2

1

このプロジェクトのように Android でプレーンな CLI インターフェイスを使用してみましたか? シンプルな fileProcesssor インターフェイスを使用できます: IN=ogg OUT=raw-pcm

.ogg から PCM 形式への変換については、以下の CLI を参照してください。次に、出力で何でもします

 rob@ Downloads$ ffmpeg -i Example.ogg -f s16le -acodec pcm_s16le output.raw

ffmpeg version N-35901-g27a3415 Copyright (c) 2000-2012 the FFmpeg developers
  built on Oct  7 2012 12:06:43 with gcc 4.6 (Ubuntu/Linaro 4.6.3-1ubuntu5)
  configuration: --enable-gpl --enable-libfaac --enable-libfdk-aac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-librtmp --enable-libtheora --enable-libvorbis --enable-libvpx --enable-x11grab --enable-libx264 --enable-nonfree --enable-version3
  libavutil      51. 73.102 / 51. 73.102
  libavcodec     54. 64.100 / 54. 64.100
  libavformat    54. 29.105 / 54. 29.105
  libavdevice    54.  3.100 / 54.  3.100
  libavfilter     3. 19.102 /  3. 19.102
  libswscale      2.  1.101 /  2.  1.101
  libswresample   0. 16.100 /  0. 16.100
  libpostproc    52.  1.100 / 52.  1.100
[NULL @ 0x186b840] Invalid packet
Input #0, ogg, from 'Example.ogg':
  Duration: 00:00:06.10, start: 0.000000, bitrate: 137 kb/s
    Stream #0:0: Audio: vorbis, 44100 Hz, stereo, s16, 160 kb/s
Output #0, s16le, to 'output.raw':
  Metadata:
    encoder         : Lavf54.29.105
    Stream #0:0: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (vorbis -> pcm_s16le)
Press [q] to stop, [?] for help
size=    1054kB time=00:00:06.11 bitrate=1411.2kbits/s    
video:0kB audio:1054kB subtitle:0 global headers:0kB muxing overhead 0.000000%

これは、OGG LIB依存関係を使用してAndroid用のffmpegを構成/作成できることを前提としていますが、これはトリッキーなプロセスになる可能性があります...

于 2013-02-27T15:51:27.717 に答える
1

最小サイズのバッファーを使用して、ストリーミング モードで AudioTrack を作成します。一部のデータを変換している場合、一部のデータを書き込んでいる場合、オーディオ再生でギャップが発生している可能性があります。これは、変換で SD カードからの読み取りを継続する必要がある場合に特に当てはまります。AudioTrack バッファーのサイズを増やして、これが要因であるかどうかを確認できます。

また、よくわかりませんが、avcodec_decode_audio3 は &out_size を short のサイズとして設定する可能性があると思いますが、これは AudioTrack にバイト単位のサイズとして送信されます (API とそのバイトをチェックするだけではありません)。

于 2013-02-27T15:21:29.443 に答える