2016-04-05 9 views
0

Ich versuche, das Audio zu entschlüsseln und zeichnen die Wellenform mit ffmpeg, und die Eingabe Audiodaten ist AV_SAMPLE_FMT_S16P, im Grunde bin ich im Anschluss an das Tutorial here, und das Audio spielt gut mit libao. Jetzt muss ich die Wellenform mit decodierten Daten plotten, derzeit schreibe ich linken und rechten Kanal, um CSV-Datei zu trennen und auf Excel zu zeichnen. Die Wellenform unterscheidet sich jedoch von der in Audacity mit demselben Audioclip gezeigten Wellenform. Wenn ich den auf csv geschriebenen Wert analysierte, sind die meisten Werte nahe bei Maximum von uint16_t (65535), aber es gibt einige andere niedrigere Werte, aber Mehrheit ist hoher Höchstwert.FFMPEG Audio dekodieren und zeichnen Wellenform

Hier ist der Quellcode,

const char* input_filename="/home/user/Music/Clip.mp3"; 
    av_register_all(); 
    AVFormatContext* container=avformat_alloc_context(); 
    if(avformat_open_input(&container,input_filename,NULL,NULL)<0){ 
     endApp("Could not open file"); 
    } 

    if(avformat_find_stream_info(container, NULL)<0){ 
     endApp("Could not find file info"); 
    } 

    av_dump_format(container,0,input_filename,false); 

    int stream_id=-1; 
    int i; 
    for(i=0;i<container->nb_streams;i++){ 
     if(container->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){ 
      stream_id=i; 
      break; 
     } 
    } 
    if(stream_id==-1){ 
     endApp("Could not find Audio Stream"); 
    } 

    AVDictionary *metadata=container->metadata; 

    AVCodecContext *ctx=container->streams[stream_id]->codec; 
    AVCodec *codec=avcodec_find_decoder(ctx->codec_id); 

    if(codec==NULL){ 
     endApp("cannot find codec!"); 
    } 

    if(avcodec_open2(ctx,codec,NULL)<0){ 
     endApp("Codec cannot be found"); 
    } 



    AVPacket packet; 
    av_init_packet(&packet); 

    //AVFrame *frame=avcodec_alloc_frame(); 
    AVFrame *frame=av_frame_alloc(); 

    int buffer_size=AVCODEC_MAX_AUDIO_FRAME_SIZE+ FF_INPUT_BUFFER_PADDING_SIZE; 

    // MSVC can't do variable size allocations on stack, ohgodwhy 
    uint8_t *buffer = new uint8_t[buffer_size]; 
    packet.data=buffer; 
    packet.size =buffer_size; 

    int frameFinished=0; 

    int plane_size; 

    ofstream fileCh1,fileCh2; 
    fileCh1.open ("ch1.csv"); 
    fileCh2.open ("ch2.csv"); 

    AVSampleFormat sfmt=ctx->sample_fmt; 

    while(av_read_frame(container,&packet)>=0) 
    { 

     if(packet.stream_index==stream_id){ 
      int len=avcodec_decode_audio4(ctx,frame,&frameFinished,&packet); 
      int data_size = av_samples_get_buffer_size(&plane_size, ctx->channels, 
               frame->nb_samples, 
               ctx->sample_fmt, 1); 


      if(frameFinished){ 
       int write_p=0; 
       // QTime t; 
       switch (sfmt){ 

        case AV_SAMPLE_FMT_S16P: 

         for (int nb=0;nb<plane_size/sizeof(uint16_t);nb++){ 
          for (int ch = 0; ch < ctx->channels; ch++) { 
           if(ch==0) 
            fileCh1 <<((uint16_t *) frame->extended_data[ch])[nb]<<"\n"; 
           else if(ch==1) 
            fileCh2 <<((uint16_t *) frame->extended_data[ch])[nb]<<"\n"; 
          } 
         } 

         break; 

       } 
      } else { 
       DBG("frame failed"); 
      } 
     } 


     av_free_packet(&packet); 
    } 
    fileCh1.close(); 
    fileCh2.close(); 
    avcodec_close(ctx); 
    avformat_close_input(&container); 
    delete buffer; 
    return 0; 

Edit:

ich die Wellenform Bild zeichnen opencv mit beiliegendem haben, hier habe ich den Abtastwert zu 0-255 Bereich skaliert und Wert nahm 127 als 0 (Y-Achse). Nun für jede Probenentnahmeleitung von (x, 127) bis (x, Abtastwert) wobei x = 1,2,3, ...

enter image description here

+0

Das Gießen der Probenwerte scheint Präzision zu verlieren. Welche Ausgabe erhalten Sie, wenn Sie den Beispielwert mit 'printf' formatieren? – benardier

+0

Den Wert in drei Methoden wie 'printf ("% u ", (unsigned short) aus [write_p]);', 'cout << (unsigned short) aus [write_p];', 'cout << (int) out [write_p]; 'gib mir die gleichen Werte. Dieser Wert unterscheidet sich jedoch von der Ausgabe der CSV-Datei. – Haris

+1

Neugierig. Warum werden Sie auf uint16_t umgestellt, wenn das Format 16-Bit-Zeichen enthält? – jaket

Antwort

1

Das Problem ist die Umwandlung in uint16_t wenn die Probe Das Format ist signiert (AV_SAMPLE_FMT_S16P, wobei S für signiert steht). Aus diesem Grund wird -1 als 2147483648 in die Datei geschrieben.

es zu beheben, die Linien ändern:

fileCh1 <<((uint16_t *) frame->extended_data[ch])[nb]<<"\n"; 

zu:

fileCh1 <<((int16_t *) frame->extended_data[ch])[nb]<<"\n"; 
Verwandte Themen