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(¶ms);
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;
}
내 실제 코드는 모든 반환 값을 확인하지만, 게시 목적으로 만 단축했습니다. int에서 short로 변경하면 WAV가 올바르게 재생됩니다 ... 감사합니다! –