英文:
Is it possible to get length (in seconds) of a loaded WAV file in SDL library?
问题
I am trying to find a way to get the duration of an WAV audio file loaded in SDL library.
我正在尝试找到一种方法来获取在SDL库中加载的WAV音频文件的持续时间。
I am using the latest official build of SDL for Windows, 64-bit, version 2.26.5.
我正在使用Windows的最新官方版本SDL构建,64位,版本2.26.5。
SDL provides following data about the loaded file after a call to LoadWAV
function.
SDL在调用LoadWAV
函数后提供了以下有关加载文件的数据。
Here we have SDL_AudioSpec
which I describe below, and audio_len
which is simply the file size in bytes.
这里我们有SDL_AudioSpec
,我将在下面描述,以及audio_len
,它只是文件大小(以字节为单位)。
typedef struct SDL_AudioSpec
{
int freq;
SDL_AudioFormat format;
Uint8 channels;
Uint8 silence;
Uint16 samples;
Uint16 padding;
Uint32 size;
SDL_AudioCallback callback;
void *userdata;
} SDL_AudioSpec;
The file which I load was taken from the system, it is located in C:\Windows\Media
folder, so this file must be 100% correct.
我加载的文件来自系统,位于C:\Windows\Media
文件夹中,因此这个文件必须是100%正确的。
After I load my WAV file, I see only two fields of SDL_AudioSpec
filled in. These fields are: freq
and format
. All other fields are zeroed. File size in bytes is filled into another function argument, but it does not mean anything to me while it is set in bytes instead of time units like second of millisecond.
加载完我的WAV文件后,我只看到SDL_AudioSpec
的两个字段被填充了。这些字段是:freq
和format
。所有其他字段都被清零。文件大小以字节填充到另一个函数参数中,但对我来说它没有任何意义,因为它是以字节而不是时间单位(如秒或毫秒)设置的。
I have searched in documentation of SDL, but I do not see other ways to get the file length in seconds, or simply, file duration in seconds.
我已经在SDL的文档中搜索过,但我没有看到其他获取文件长度(以秒为单位)或简单地说,文件持续时间(以秒为单位)的方法。
Is it really possible to get WAV file duration using only SDL library without any other third-party tools ?
只使用SDL库而不使用任何其他第三方工具是否真的可以获取WAV文件的持续时间?
UPDATE
I found the reason for zeroed values. I was using a 16-bit int size instead of 32-bit int. Forgive me, MS-DOS, the world has changed.
我找到了零值的原因。我使用了16位整数大小而不是32位整数。原谅我,MS-DOS,世界已经改变了。
英文:
I am trying to find a way to get the duration of an WAV audio file loaded in SDL library.
I am using the latest official build of SDL for Windows, 64-bit, version 2.26.5.
SDL provides following data about the loaded file after a call to LoadWAV
function.
SDL_AudioSpec* SDL_LoadWAV(const char* file,
SDL_AudioSpec* spec,
Uint8** audio_buf,
Uint32* audio_len)
Here we have SDL_AudioSpec
which I describe below, and audio_len
which is simply the file size in bytes.
typedef struct SDL_AudioSpec
{
int freq;
SDL_AudioFormat format;
Uint8 channels;
Uint8 silence;
Uint16 samples;
Uint16 padding;
Uint32 size;
SDL_AudioCallback callback;
void *userdata;
} SDL_AudioSpec;
The file which I load was taken from the system, it is located in C:\Windows\Media
folder, so this file must be 100% correct.
After I load my WAV file, I see only two fields of SDL_AudioSpec
filled in. These fields are: freq
and format
. All other fields are zeroed. File size in bytes is filled into another function argument, but it does not mean anything to me while it is set in bytes instead of time units like second of millisecond.
I have searched in documentation of SDL, but I do not see other ways to get the file length in seconds, or simply, file duration in seconds.
Is it really possible to get WAV file duration using only SDL library without any other third-party tools ?
UPDATE
I found the reason for zeroed values. I was using a 16-bit int size instead of 32-bit int. Forgive me, MS-DOS, the world has changed.
答案1
得分: 1
The audio_len
output parameter 是已加载的音频缓冲区的字节长度,不是文件的大小。在处理音频缓冲区时,SDL 通常以字节为单位指定大小。
所以将其转换为秒的步骤非常简单:将缓冲区长度除以采样大小以获得所有通道的样本数。然后再除以通道数以获得样本中的音频剪辑长度。然后将其除以频率以获得以秒为单位的长度。
未经测试的代码:
double howManySeconds(const char *filename) {
SDL_AudioSpec spec;
uint32_t audioLen;
uint8_t *audioBuf;
double seconds = 0.0;
if(SDL_LoadWAV(filename, &spec, &audioBuf, &audioLen) != NULL) {
// 我们在此示例中未使用实际音频
SDL_FreeWAV(audioBuf);
uint32_t sampleSize = SDL_AUDIO_BITSIZE(spec.format) / 8;
uint32_t sampleCount = audioLen / sampleSize;
// 可以进行健全性检查,确保 (audioLen % sampleSize) 为 0
uint32_t sampleLen = 0;
if(spec.channels) {
sampleLen = sampleCount / spec.channels;
} else {
// spec.channels *should* be 1 or higher, but just in case
sampleLen = sampleCount;
}
seconds = (double)sampleLen / (double)spec.freq;
} else {
// 出现问题!
fprintf(stderr, "错误:无法加载:%s:%s\n", filename, SDL_GetError());
}
return seconds;
}
英文:
The audio_len
output parameter is the length of the loaded audio buffer in bytes, not the size of the file. When dealing with audio buffers, SDL generally specifies the size in bytes.
So the steps to convert to seconds are pretty simple: divide the buffer length by the sample size to get the number of samples across all channels. Then divide by the number of channels to get the length of the audio clip in samples. Then divide that by the frequency to get the length in seconds.
Untested code:
double howManySeconds(const char *filename) {
SDL_AudioSpec spec;
uint32_t audioLen;
uint8_t *audioBuf;
double seconds = 0.0;
if(SDL_LoadWAV(filename, &spec, &audioBuf, &audioLen) != NULL) {
// we aren't using the actual audio in this example
SDL_FreeWAV(audioBuf);
uint32_t sampleSize = SDL_AUDIO_BITSIZE(spec.format) / 8;
uint32_t sampleCount = audioLen / sampleSize;
// could do a sanity check and make sure (audioLen % sampleSize) is 0
uint32_t sampleLen = 0;
if(spec.channels) {
sampleLen = sampleCount / spec.channels;
} else {
// spec.channels *should* be 1 or higher, but just in case
sampleLen = sampleCount;
}
seconds = (double)sampleLen / (double)audioSpec.freq;
} else {
// uh-oh!
fprintf(stderr, "ERROR: can't load: %s: %s\n", filename, SDL_GetError());
}
return seconds;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论