2015-01-06 2 views
7

ALSA 오디오 레이어를 학습하여 결국 Raspberry Pi 플랫폼 용 ALSA 장치 드라이버를 작성하려고합니다. 간단히 말하면, ALSA 프로젝트 사이트와 다른 온라인 소스의 다양한 샘플을 함께 붙여서 가장 간단한 작업을 수행했습니다. WAV 파일을 읽고 기본 사운드 장치에서 재생합니다. 이 간단한 C 샘플을 사용할 수 없습니다.라즈베리 파이에서 WAV 파일을 읽고 재생하는 ALSA 응용 프로그램

libsndfile을 사용하여 모든 WAV 파일 읽기/헤더 디코딩을 수행하고 있습니다. 버퍼에 읽은 샘플이 올바른지 확인합니다 (샘플 값을 텍스트 파일에 덤프하는 sndfile-to-text 응용 프로그램에 대해 프로그램이 읽는 내용의 처음 400K 샘플을 확인). 그래서 내 버퍼에 올바른 데이터가 들어 있다는 것을 알고, 문제는 ALSA API에 전달하는 방식이어야합니다.

실행하면 소리가 오른쪽 채널에서만 생성되고 왜곡되거나 흐릿 해져 거의 알아볼 수 없습니다. BTW, "aplay"응용 프로그램은 동일한 WAV 파일을 완벽하게 재생하며 파일에 16 비트로 서명 된 LE, 44100Hz, 스테레오는 내 응용 프로그램 보고서와 일치한다고보고합니다. 이것을 라스베리 파이에서 실행합니다.

여기 공간을 절약하기 위해 C 프로그램을 최소한으로 제거했지만 모든 API 호출에서 올바른 리턴 코드를 확인했습니다. 이 간단한 ALSA 응용 프로그램이 올바른 사운드를 생성하지 않는 이유는 무엇입니까?

#include <alsa/asoundlib.h> 
#include <stdio.h> 
#include <sndfile.h> 

#define PCM_DEVICE "default" 

int main(int argc, char **argv) { 

    snd_pcm_t *pcm_handle; 
    snd_pcm_hw_params_t *params; 
    snd_pcm_uframes_t frames; 
    int dir, pcmrc; 

    char *infilename = "/home/pi/shortsample.wav"; 
    int* buf = NULL; 
    int readcount; 

    SF_INFO sfinfo; 
    SNDFILE *infile = NULL; 

    infile = sf_open(infilename, SFM_READ, &sfinfo); 
    fprintf(stderr,"Channels: %d\n", sfinfo.channels); 
    fprintf(stderr,"Sample rate: %d\n", sfinfo.samplerate); 
    fprintf(stderr,"Sections: %d\n", sfinfo.sections); 
    fprintf(stderr,"Format: %d\n", sfinfo.format); 

    /* Open the PCM device in playback mode */ 
    snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); 

    /* Allocate parameters object and fill it with default values*/ 
    snd_pcm_hw_params_alloca(&params); 
    snd_pcm_hw_params_any(pcm_handle, params); 
    /* Set parameters */ 
    snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); 
    snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); 
    snd_pcm_hw_params_set_channels(pcm_handle, params, sfinfo.channels); 
    snd_pcm_hw_params_set_rate(pcm_handle, params, sfinfo.samplerate, 0); 

    /* Write parameters */ 
    snd_pcm_hw_params(pcm_handle, params); 

    /* Allocate buffer to hold single period */ 
    snd_pcm_hw_params_get_period_size(params, &frames, &dir); 
    fprintf(stderr,"# frames in a period: %d\n", frames); 

    fprintf(stderr,"Starting read/write loop\n"); 
    buf = malloc(frames * sfinfo.channels * sizeof(int)); 
    while ((readcount = sf_readf_int(infile, buf, frames))>0) { 

     pcmrc = snd_pcm_writei(pcm_handle, buf, readcount); 
     if (pcmrc == -EPIPE) { 
      fprintf(stderr, "Underrun!\n"); 
      snd_pcm_prepare(pcm_handle); 
     } 
     else if (pcmrc < 0) { 
      fprintf(stderr, "Error writing to PCM device: %s\n", snd_strerror(pcmrc)); 
     } 
     else if (pcmrc != readcount) { 
      fprintf(stderr,"PCM write difffers from PCM read.\n"); 
     } 

    } 
    fprintf(stderr,"End read/write loop\n"); 

    snd_pcm_drain(pcm_handle); 
    snd_pcm_close(pcm_handle); 
    free(buf); 

    return 0; 
} 

답변

4

당신 실패 할 수있는 모든 snd_ 함수의 반환 값을 확인해야합니다.

S16_LE 형식에는 샘플 당 2 바이트가 있지만 int에는 4가 있습니다. 대신 short을 사용하고 sf_readf_short을 사용하십시오.

+0

내 실제 코드는 모든 반환 값을 확인하지만, 게시 목적으로 만 단축했습니다. int에서 short로 변경하면 WAV가 올바르게 재생됩니다 ... 감사합니다! –

관련 문제