可以获取已加载的WAV文件在SDL库中的长度(以秒为单位)吗?

huangapple go评论55阅读模式
英文:

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的两个字段被填充了。这些字段是:freqformat。所有其他字段都被清零。文件大小以字节填充到另一个函数参数中,但对我来说它没有任何意义,因为它是以字节而不是时间单位(如秒或毫秒)设置的。

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;
}

huangapple
  • 本文由 发表于 2023年4月17日 04:38:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76030221.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定