2016-04-05 29 views
0

çizmek ben ses kodlarını ve ffmpeg kullanarak dalga biçimini çizmek çalışıyorum, ve giriş ses verileri AV_SAMPLE_FMT_S16P olduğunu temelde ben öğretici here takip ediyorum ve ses libao ince oynuyor. Şimdi dalga formunu kodu çözülmüş verileri kullanarak çizmem gerekiyor, şu anda csv dosyasını ayırmak ve excel üzerinde çizim yapmak için sol ve sağ kanal yazıyorum. Ancak dalga biçimi, aynı ses klibi kullanılarak Audacity'de gösterilen dalga formundan farklı bir şeydir. Csv üzerine yazılan değeri analiz ettiğimde, değerlerin çoğu uint16_t (65535) değerine yakındır, fakat diğer bazı düşük değerler vardır, ancak çoğunluğu yüksek tepe noktasıdır. İşte FFMPEG Ses kod çözme ve dalga biçimini

kaynak kodu

, Düzen
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; 

: Ben dalga görüntüsü OpenCV kullanarak çizmek iliştirilmesi

, burada 0-255 aralığına örnek değerini ölçekli ve değerini aldı 127, 0 (Y ekseni) olarak. Şimdi (x, örnek değer) ila (x, 127) her bir örnek çekme hattı için x = 1,2,3 ...

enter image description here

+0

örnek değerler döküm hassasiyetini kaybedecek gibi görünüyor. Örnek değerini "printf" ile biçimlendirdiğinizde hangi çıktıyı alırsınız? – benardier

+0

Değeri printf ("% u", (imzasız kısa) out [write_p]); '," cout << (imzasız kısa) out [write_p]; ',' cout << (int) gibi üç yöntemle bastırma [write_p]; 'bana aynı değerleri veriyor. Ancak bu değer, csv dosya çıktısından farklıdır. – Haris

+1

Meraklı. Biçim 16 bit işaretli olduğunda neden uint16_t'ye yayınlanıyorsunuz? – jaket

cevap

1

sorun uint16_t zaman numune için dökülür biçim imzalı (S'nin imzalı olduğu anlamına gelen AV_SAMPLE_FMT_S16P). Bundan dolayı -1, 2147483648 ve benzeri dosyaya yazılacak.

, bunu düzeltmek satırları değiştirmek için:

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

için:

fileCh1 <<((int16_t *) frame->extended_data[ch])[nb]<<"\n"; 
İlgili konular