我正在尝试使用 ALSA ( libasound.so.2
) 播放具有 3 字节样本对齐的 24 位 wav 文件。并且 ALSA 在设置缓冲区大小时失败并Invalid argument
出现错误(并且 ALSA 不会将任何内容传递给驱动程序)
这是wav
文件头内容:
chunkId: 46464952
chunkSize: 221417340
format: "WAVE"
subchunk1Id: "fmt "
subchunk1Size: 40
audioFormat: fffe
numChannels: 2
sampleRate: 88200
byteRate: 529200
blockAlign: 6
bitsPerSample: 24
cbSize 16
wValidBitsPerSample 18
dwChannelMask 0
SubFormat
subchunk2Id: "data"
subchunk2Size: 221417280
不幸的是无法提供适当的测试程序源,因为它是跨平台程序的一部分并且不会单独构建。缩短示例可能看起来像
#include <stdio.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <semaphore.h>
#include "asoundlib.h"
int main(int argc, char *argv[])
{
int err = -1; /**< ALSA & clib function return code */
snd_pcm_t *p_handle = NULL; /**< pointer to active pcm object */
static const char *const p_device = "default"; /**< const pointer to const device id string */
unsigned int sampleRate = 0;
unsigned int rbuffertime = 0; /**< real buffer time as granted by ALSA */
err = snd_pcm_open(&p_handle, p_device, SND_PCM_STREAM_PLAYBACK, 0);
if (0 > err)
{
printf("Playback open error: %s\n", snd_strerror(err));
return err;
}
/* Get full range of possible hw params */
err = snd_pcm_hw_params_any(p_handle, p_hwparams);
if (0 > err)
{
printf("Error fetching hw param ranges: %s\n", snd_strerror(err));
return err;
}
// Specify a specific config out of configuration space and set it
err = snd_pcm_hw_params_set_rate_resample(p_handle, p_hwparams, 1);
if (0 > err)
{
printf("Unable to snd_pcm_hw_params_set_rate_resample for playback: %s\n", snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_set_access(p_handle, p_hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
if (0 > err)
{
printf("Unable to snd_pcm_hw_params_set_access for playback: %s\n", snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_set_format(p_handle, p_hwparams, SND_PCM_FORMAT_S24_3LE);
if (0 > err)
{
printf("Unable to snd_pcm_hw_params_set_format for playback: %s\n", snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_set_channels(p_handle, p_hwparams, 2);
if (0 > err)
{
printf("Unable to snd_pcm_hw_params_set_channels for playback: %s\n", snd_strerror(err));
return err;
}
sampleRate = 88200;
err = snd_pcm_hw_params_set_rate_near(p_handle, p_hwparams, &sampleRate, 0);
if (0 > err)
{
printf("Unable to snd_pcm_hw_params_set_rate for playback: %s\n", snd_strerror(err));
return err;
}
rbuffertime = 500000;
err = snd_pcm_hw_params_set_buffer_time_near(p_handle, p_hwparams, &rbuffertime, 0);
if (0 > err)
{
printf("Unable to snd_pcm_hw_params_set_buffer_time_near for playback: %s\n", snd_strerror(err));
}
return err;
}
ALSAsnd_pcm_hw_params_set_buffer_time_near()
呼叫失败并出现错误
ALSA ERROR hw_params: set_near (BUFFER_TIME)
value = 500000 : Invalid argument
ACCESS: RW_INTERLEAVED
FORMAT: S24_3LE
SUBFORMAT: STD
SAMPLE_BITS: 24
FRAME_BITS: 48
CHANNELS: 2
RATE: 88200
PERIOD_TIME: (476 247688)
PERIOD_SIZE: (42 21846)
PERIOD_BYTES: [256 131072]
PERIODS: [2 1024]
BUFFER_TIME: (495351 495352)
BUFFER_SIZE: 43690
BUFFER_BYTES: [262144 262140]
TICK_TIME: ALL
(ALSA 甚至不尝试将任何数据传递给驱动程序,只是在设置缓冲区失败)该程序适用于 16 位音频。
我尝试了不同的缓冲区值(0.001 .. 1 秒),但它们都不起作用。假设我错过了 24 位 3LE 所需的 ALSA 配置的任何部分,也许是对先前初始化步骤结果的一些检查?
不幸的是,我找不到任何 24 位 ALSA 用法的示例,如果您建议任何指向示例/推荐/文档的链接,我将不胜感激。
已编辑
该文件的结果aplay
是:
aplay -v /export/target/24bit_88.2kHz.wav
Playing WAVE '/export/target/24bit_88.2kHz.wav' : Signed 24 bit Little Endian in 3bytes, Rate 88200 Hz, Stereo
aplay: set_params:979: Sample format non available