Alsa,无法依次播放同一首曲目

问题描述 投票:1回答:1

我已经开发了一些代码来播放音频(波形文件)。当我尝试播放同一文件两次时,第一次播放正常,但是第二次调用时总是失败。

下面是一次性音频初始化功能。

void audio_init(void)
{
unsigned int pcm = 0;

infile = sf_open(infilename, SFM_READ, &sfinfo);

printf("\r\n");
printf("[FILE]Channels      : %d\n", sfinfo.channels);
printf("[FILE]Sample rate   : %d\n", sfinfo.samplerate);
printf("[FILE]Sections      : %d\n", sfinfo.sections);
printf("[FILE]Format        : %d\n", sfinfo.format);
printf("\r\n");

/* Open the PCM device in playback mode */
if ((pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
    printf("ERROR: Can't open \"%s\" PCM device. %s\n",PCM_DEVICE, snd_strerror(pcm));

/* Allocate parameters object and fill it with default values*/
snd_pcm_hw_params_alloca(&params);
snd_pcm_hw_params_any(pcm_handle, params);

/* Interleaved mode */
if ((pcm = snd_pcm_hw_params_set_access(pcm_handle, params,
        SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
    printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));

/* Signed 16 bit little-endian format */
if ((pcm = snd_pcm_hw_params_set_format(pcm_handle, params,
        SND_PCM_FORMAT_S16_LE)) < 0)
    printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));

/* Two channels, stereo */
if ((pcm = snd_pcm_hw_params_set_channels(pcm_handle, params, channels)) < 0)
    printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));

/* 44100 bits/second sampling rate (CD quality) */
if ((pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0)) < 0)
    printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm));

/* Write parameters to the driver */
if ((pcm = snd_pcm_hw_params(pcm_handle, params) < 0))
    printf("ERROR: Can't set harware parameters. %s\n", snd_strerror(pcm));

/* Resume information */
printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle));
printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));

int tmp = 0;
snd_pcm_hw_params_get_channels(params, &tmp);
printf("channels: %i ", tmp);

if (tmp == 1)
    printf("(mono)\n");
else if (tmp == 2)
    printf("(stereo)\n");

snd_pcm_hw_params_get_rate(params, &tmp, 0);
printf("rate: %d bps\n", tmp);

/* Allocate large enough buffer to hold single period (No. of samples) */
snd_pcm_hw_params_get_period_size(params, &frames, 0);
printf("period size = %d frames\n", (int)frames);

/* Get the period time */
snd_pcm_hw_params_get_period_time(params, &tmp, NULL);
printf("period time = %d us\n", tmp);

audio_playTrack();
printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));
sleep(5);
audio_playTrack();
printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));
}

下面是我在audio_init()末尾两次调用的函数。

void audio_playTrack(void)
{
short int* buf = NULL;
int readcount = 0;
int pcmrc;

printf("+------------------\n");
printf("### AUDIO BEGIN ###\n");
printf("+------------------\n\n");
buf = malloc(frames * sfinfo.channels * sizeof(int));
while ((readcount = sf_readf_short(infile, buf, frames))>0)
{
    pcmrc = snd_pcm_writei(pcm_handle, buf, readcount);
    if (pcmrc == -EPIPE)
    {
        printf("Underrun!\n");
        snd_pcm_prepare(pcm_handle);
    }
    else if (pcmrc < 0)
    {
        printf("Error writing to PCM device: %s\n", snd_strerror(pcmrc));
    }
    else if (pcmrc != readcount)
    {
        printf("PCM write differs from PCM read.\n");
    }
}
printf("readcount = %d\r\n", readcount);
printf("+------------------\n");
printf("### AUDIO END ###\n");
printf("+------------------\n\n");
snd_pcm_drain(pcm_handle);
//snd_pcm_close(pcm_handle);
free(buf);
}

对第一个audio_playTrack()的调用起作用。第二个不起作用,因为sf_readf_short返回0帧,甚至不进入while循环。

我希望能够随时从代码内停止音频并重新启动音频。有人可以帮助我理解为什么sf_readf_short在第二次调用时返回0且audio_playTrack()失败吗?

c alsa libsndfile
1个回答
0
投票

两个调用的文件对象infile是相同的。因此,您第一次到达文件末尾,然后第二次尝试播放时,您仍在文件末尾。您要么需要关闭然后重新打开文件,要么倒带到开头,然后再次尝试播放。

© www.soinside.com 2019 - 2024. All rights reserved.