2015-09-10 13 views
0

Я пытаюсь реализовать очень простой ogg-плеер. Он в основном открывает файл ogg, проверяет его и запускает через libvorbisfile-декодер в ALSA PCM. Проблема в том, что звук очень искажен, лагги, и для прослушивания оригинального музыкального файла требуется довольно много воображения. Оба файла alsa и ogg кодируются с частотой 44100 Гц, двумя каналами и 16-битным размером выборки.Реализация звукового плеера с помощью ALSA и Ogg vorbis в C

Вот исходный код:

#include <stdio.h> 
#include <stdlib.h> 
#include <vorbis/vorbisfile.h> 
#include <alsa/asoundlib.h> 

char *buffer; 
static char *device = "default"; 

int main(int argc, char **argv) 
{ 
    buffer = (char *) malloc(4096); 
    int err; 
    snd_pcm_t *handle; 
    snd_pcm_sframes_t frames; 

    if((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) 
      < 0) { 
     printf("Playback open error: %s\n", snd_strerror(err)); 
     exit(EXIT_FAILURE); 
    } 
    if((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE, 
      SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000)) 
      < 0) { /* 0.5sec */ 
     printf("Playback open error: %s\n", snd_strerror(err)); 
     exit(EXIT_FAILURE); 
    } 

    OggVorbis_File vf; 
    int eof = 0; 
    int current_section; 

    err = ov_fopen("zedd.ogg", &vf); 
    if(err != 0) { 
     perror("Error opening file"); 
    } else { 
     vorbis_info *vi = ov_info(&vf, -1); 
     fprintf(stderr, "Bitstream is %d channel, %ldHz\n", 
       vi->channels, vi->rate); 
     fprintf(stderr, "Encoded by: %s\n\n", 
       ov_comment(&vf, -1)->vendor); 

     while(!eof) { 
      long ret = ov_read(&vf, buffer, 4096, 0, 2, 1, 
        &current_section); 
      if(ret == 0) { 
       /* EOF */ 
       eof = 1; 
      } else if(ret < 0) { 
       /* error in the stream. */ 
      } else { 
       frames = snd_pcm_writei(handle, buffer, ret); 
       snd_pcm_wait(handle, 20000); 
       if(frames < 0) 
        frames = snd_pcm_recover(handle, frames, 
          0); 
       if(frames < 0) { 
        printf("snd_pcm_writei failed: %s\n", 
          snd_strerror(err)); 
        break; 
       } 
       if(frames > 0 && frames < 4096) 
        printf("Short write (expected %li, wrote %li)\n", 
          ret, frames); 
      } 
     } 
     ov_clear(&vf); 
    } 

    snd_pcm_close(handle); 

    return (0); 
} 

Любая помощь будет очень полезно.

ответ

1

Ответ на самом деле очень простой. В функции snd_pcm_writei я пропускал не количество кадров, а количество байтов в буфере. Для 16-битного 2-канального звука один кадр четыре байта (два байта на выборку, и у нас есть два канала). Изменение вызова на frames = snd_pcm_writei(handle, buffer, ret/4); и удаление snd_pcm_wait (избыточное в режиме блокировки) устраняет все проблемы. Многие из них для парней в #xiph на irc.freenode.net.

 Смежные вопросы

  • Нет связанных вопросов^_^